最近在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; } }
