我的练习项目用的是ant design pro,直接上代码
项目demo地址 点我打开
//index.tsx
import React, { useState, useRef, useEffect } from 'react';
import { message } from 'antd';
import styles from './index.less';
const Index = () => {
const [visible, setVisible] = useState<boolean>(false); //菜单显隐藏
const contextMenu = useRef<HTMLDivElement | any>(null); //ref
const currentEvent = useRef<MouseEvent | any>(null); //ref
// 右键事件监听
const _handleContextMenu = (event: any) => {
event.preventDefault();
setVisible(true);
currentEvent.current = event;
};
const _handleClick = (event: any) => {
const wasOutside = !(event.target.contains === contextMenu);
// 点击其他位置需要隐藏菜单
if (wasOutside) setVisible(false);
};
const _handleScroll = () => {
if (visible) setVisible(false);
};
useEffect(() => {
if (!visible) return;
const clickX = currentEvent.current.clientX;
const clickY = currentEvent.current.clientY;
const rootW = contextMenu.current.offsetWidth;
const rootH = contextMenu.current.offsetHeight;
const screenW = window.innerWidth;
const screenH = window.innerHeight;
const right = screenW - clickX > rootW;
const left = !right;
const top = screenH - clickY > rootH;
const bottom = !top;
if (right) {
contextMenu.current.style.left = `${clickX + 5}px`;
}
if (left) {
contextMenu.current.style.left = `${clickX - rootW - 5}px`;
}
if (top) {
contextMenu.current.style.top = `${clickY + 5}px`;
}
if (bottom) {
contextMenu.current.style.top = `${clickY - rootH - 5}px`;
}
}, [visible]);
useEffect(() => {
// 事件监听
document.addEventListener('contextmenu', _handleContextMenu);
document.addEventListener('click', _handleClick);
document.addEventListener('scroll', _handleScroll);
return () => {
// 组件卸载移除事件监听
document.removeEventListener('contextmenu', _handleContextMenu);
document.removeEventListener('click', _handleClick);
document.removeEventListener('scroll', _handleScroll);
};
}, []);
// 菜单事件处理
const menuHandle = (type: number) => {
setVisible(false);
message.success(`点击了菜单${type}`);
};
return (
visible && (
<div ref={contextMenu} className={styles.contextMenu}>
<div className={styles.menuList} onClick={() => menuHandle(1)}>
菜单1
</div>
<div className={styles.menuList} onClick={() => menuHandle(2)}>
菜单2
</div>
<div className={styles.menuList} onClick={() => menuHandle(3)}>
菜单3
</div>
<div className={styles.menuList} onClick={() => menuHandle(4)}>
菜单4
</div>
</div>
)
);
};
export default Index;
//index.less
.contextMenu {
background-color: #000;
width: 66px;
padding-top: 5px;
position: fixed;
.menuList {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
color: #fff;
text-align: center;
border-bottom: 1px solid #fff;
height: 25px;
cursor: pointer;
}
}