自己封装的一套右键菜单组件,id必须唯一且一致,不能以数字开头,否则queryselector会报错。
contextmenu.js
import React, { Fragment, useEffect, useMemo } from "react";
import "./contextMenu.less";
//<ContextMenuTrigger>和<ContextMenu>的id必须唯一且一致,id必须以字母开头,如果以数字开头,querySelector会有问题
function ContextMenu(props) {
const { id, options } = props;
const handleClick = (ev, onClick) => {
if (onClick && typeof onClick == "function") {
onClick(ev);
};
if (/^\d+/.test(id)) {
console.warn("ID should be start with string!");
return;
}
let dom = document.querySelector(`#${id}`);
if (dom) {
dom.style.display = "none";
}
}
const renderLi = useMemo(() => {
return options && options.map((item, index) => {
const { label, onClick } = item;
return <li key={`contextMenu-li-${index}`} onClick={(ev) => handleClick(ev, onClick)}>
{label}
</li>
})
}, [options]);
return (
<div id={id} className="contextMenu" style={{ display: "none" }}>
<ul>
{renderLi}
</ul>
</div>
)
}
let clickIds = {};
function ContextMenuTrigger(props) {
const { children, id } = props;
useEffect(() => {
if (!clickIds[id]) {
document.addEventListener("mousedown", onMouseDown, false);
clickIds[id] = 1;
}
return () => {
document.removeEventListener("mousedown", onMouseDown, false);
clickIds = {};
}
}, [])
const onMouseDown = (ev) => {
if (/^\d+/.test(id)) {
console.warn("ID should be start with string!");
return;
}
let dom = document.querySelector(`#${id}`);
if (dom) {
let clientRect = dom.getBoundingClientRect();
const { clientX, clientY } = ev;
const { x, y, width, height } = clientRect;
if (!(clientX >= x && clientX <= x + width && clientY >= y && clientY <= y + height)) {
dom.style.display = "none";
}
}
}
const onContextMenu = (ev) => {
if (/^\d+/.test(id)) {
console.warn("ID should be start with string!");
return;
}
let dom = document.querySelector(`#${id}`);
if (dom) {
dom.style.display = "block";
dom.style.left = ev.clientX + "px";
dom.style.top = ev.clientY + "px";
}
ev.preventDefault();
}
const newChildren = React.cloneElement(children, { onContextMenu: onContextMenu });
return <Fragment>
{newChildren}
</Fragment>
}
ContextMenu.defaultProps = {
options: [],
}
export { ContextMenu, ContextMenuTrigger };
contextmenu.less
.contextMenu {
position : fixed;
background-color: white;
border : 1px solid #888888;
box-shadow : 2px 2px 3px 0px #888888;
z-index : 999;
cursor : default;
ul {
li {
padding: 5px;
&:hover {
background-color: #dddddd;
}
}
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。