当我们在网页内使用鼠标右键点击页面,浏览器将显示默认的上下文菜单。这篇文章介绍如何将默认的上下文菜单替换为我们的自定义菜单,允许执行一些自定义操作。
我们先创建一个想要显示自定义上下文菜单的元素。
<div id="element">右键点击div>
<div id="menu">我是菜单div>
阻止显示默认的上下文菜单
想要做到这点,只需要在 contextmenu 事件内阻止默认行为即可。
const el = document.getElementById('element');
el.addEventListener('contextmenu', function (e) {
e.preventDefault();
});
在点击的位置显示自定义菜单
自定义菜单位置需要通过计算得出,在计算之前,需将其定位到某个容器内。因此,我们需要包裹 element 和 menu。
<div id="relative">
<div id="element">div>
<div id="menu hidden">div>
div>
.relative {
position: relative;
}
.absolute {
position: absolute;
}
.hidden {
display: none;
}
接下来就可以对自定义菜单的定位进行计算,我们需要获取到鼠标位置信息和 element 容器尺寸信息。
el.addEventListener('contextmenu', function (e) {
const rect = el.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
// 设置菜单的位置
menu.style.left = `${x}px`;
menu.style.top = `${y}px`;
// 显示菜单
menu.classList.remove('hidden');
});
点击 menu 外部区域时隐藏 menu
el.addEventListener('contextmenu', function (e) {
// ...
document.addEventListener('click', handleClickDocument);
});
function handleClickDocument(e) {
const isClickedOutside = !menu.contains(e.target);
if (isClickedOutside) {
// 隐藏菜单
menu.classList.add('hidden');
// 移除事件
document.removeEventListener('click', handleClickDocument);
}
}
给 menu 添加 hidden class,隐藏菜单。
隐藏菜单时,同时需要移除 document 上的 click 事件,也就是说 click 事件仅执行一次。
让事件只执行一次的还有另一种方式,在 addEventListener 方法传入第三个参数 { once: true }
。
document.addEventListener('click', handleClickDocument, { once: true });