• React项目中实现右键自定义菜单


      最近在react项目中需要实现一个,右键自定义菜单功能。找了找发现纯react项目里没有什么工具可以实现这样的功能,所以在网上搜了搜相关资料。下面我会附上完整的组件代码。

      (注:以下代码非本人原创,具体详情请参考 https://blog.csdn.net/anyicheng2015/article/details/78581064)

      

    import React, { Component } from 'react'
    import PropTypes from 'prop-types'
    import assign from 'object-assign'
    
    import './index.less'
    import _ from 'lodash'
    
    class RightClickContextMenu extends Component {
      static propTypes = {
        style: PropTypes.object,
        onClickVideoAudioSpeedBtn: PropTypes.func,
      }
    
      static defaultProps = {
        style: {},
        onClickVideoAudioSpeedBtn: _.noop,
      }
    
      state = {
        visible: false,
      }
    
      componentDidMount() {
        // 添加右键点击、点击事件监听
        document.addEventListener('contextmenu', this.handleContextMenu)
        document.addEventListener('click', this.handleClick)
      }
    
      componentWillUnmount() {
        // 移除事件监听
        document.removeEventListener('contextmenu', this.handleContextMenu)
        document.removeEventListener('click', this.handleClick)
      }
    
      // 右键菜单事件
      handleContextMenu = (event) => {
        event.preventDefault()
    
        this.setState({ visible: true })
    
        // clientX/Y 获取到的是触发点相对于浏览器可视区域左上角距离
        const clickX = event.clientX
        const clickY = event.clientY
        // window.innerWidth/innerHeight 获取的是当前浏览器窗口的视口宽度/高度
        const screenW = window.innerWidth
        const screenH = window.innerHeight
        // 获取自定义菜单的宽度/高度
        const rootW = this.root.offsetWidth
        const rootH = this.root.offsetHeight
    
        // right为true,说明鼠标点击的位置到浏览器的右边界的宽度可以放下菜单。否则,菜单放到左边。
        // bottom为true,说明鼠标点击位置到浏览器的下边界的高度可以放下菜单。否则,菜单放到上边。
        const right = (screenW - clickX) > rootW
        const left = !right
        const bottom = (screenH - clickY) > rootH
        const top = !bottom
    
        if (right) {
          this.root.style.left = `${clickX}px`
        }
    
        if (left) {
          this.root.style.left = `${clickX - rootW}px`
        }
    
        if (bottom) {
          this.root.style.top = `${clickY}px`
        }
        if (top) {
          this.root.style.top = `${clickY - rootH}px`
        }
      };
    
      // 鼠标单击事件,当鼠标在任何地方单击时,设置菜单不显示
      handleClick = () => {
        const { visible } = this.state
        if (visible) {
          this.setState({ visible: false })
        }
      };
    
    
      render() {
        const wrapStyles = assign({}, this.props.style)
        const { visible } = this.state
    
        return (
          visible && (
            <div ref={(ref) => { this.root = ref }} className="contextMenu-wrap" style={wrapStyles}>
              <div className="contextMenu-option">输入文字</div>
              <div className="contextMenu-option">网络连接监控</div>
              <div className="contextMenu-option" role="button" onClick={this.props.onClickVideoAudioSpeedBtn}>音视频流监控</div>
              <div className="contextMenu-option">教室权限控制</div>
              <div className="contextMenu-separator" />
              <div className="contextMenu-option">设置...</div>
              <div className="contextMenu-option">全局设置...</div>
            </div>
          )
        )
      }
    }
    
    export default RightClickContextMenu

      样式部分如下:

    .contextMenu-wrap{
      z-index: 100;
      position: fixed;
      background: linear-gradient(to right, #c6c7cf, #f0f0f0);
      box-shadow: 0px 2px 5px #999999;
      border-radius: 4px;
      padding-top: 5px;
      .contextMenu-option{
        padding: 0px 50px 2px 15px;
        min-width: 160px;
        cursor: default;
        font-size: 14px;
        &:hover {
          background: #388bfe;
          color: white;
        }
        &:active {
          color: #b5b7be;
          background: linear-gradient(to top, #555, #444);
        }
      }
      .contextMenu-separator{
        width: 100%;
        height: 1px;
        background: #b5b7be;
        margin: 2px 0;
      }
    }
  • 相关阅读:
    [luoguP2486] [SDOI2011]染色(树链剖分)
    [POJ3162]Walking Race(DP + 单调队列)
    [HDU3586]Information Disturbing(DP + 二分)
    [luoguP1280] 尼克的任务(DP)
    [luoguP1282] 多米诺骨牌(DP + 背包)
    AOJ 0558 Cheese【BFS】
    POJ 3009 Curling 2.0【带回溯DFS】
    AOJ 0033 Ball【DFS】
    AOJ 0118 Property Distribution【DFS】
    POJ 1979 Red and Black【DFS】
  • 原文地址:https://www.cnblogs.com/chenbeibei520/p/9681398.html
Copyright © 2020-2023  润新知