鼠标右击网页会弹出默认的浏览器菜单,可是不少时候咱们须要自定义右键菜单(好比:在线文档编辑器、定制视频播放器等)。今天咱们就来快速实现一个自定义右键菜单。git
预览:github
contextmenu
事件监听首先,咱们须要禁用浏览器弹出默认菜单的行为,经过阻止 contextMenu 事件的默认行为,并同时触发自定义菜单的显示:浏览器
document.addEventListener("contextmenu", (e) => { e.preventDefault(); showMenu(e); });
一个页面中菜单应该只有一个实例,因此咱们运用单例模式去建立菜单,典型的单例构造器能够实现为:app
const ContextMenu = function (options) { // 惟一实例 let instance; // 建立实例方法 function createMenu() { // todo } return { // 获取实例的惟一方式 getInstance: function () { if (!instance) { instance = createMenu(); } return instance; }, }; };
即实现上面的 createMenu
方法。编辑器
菜单的具体配置经过 options
传入,options
的结构定义为:ide
options: { menus: [{ name: string, // 菜单名称 onClick: Function // 菜单点击回调 }] }
经过遍历 options.menus
生成菜单列表,并挂载到 body
中,并最终返回菜单的实例:spa
function createMenu() { const ul = document.createElement("ul"); ul.classList.add("custom-context-menu"); const { menus } = options; if (menus && menus.length > 0) { for (let menu of menus) { const li = document.createElement("li"); li.textContent = menu.name; li.onclick = menu.onClick; ul.appendChild(li); } } const body = document.querySelector("body"); body.appendChild(ul); return ul; }
建立菜单的主要逻辑就完成了。code
接下来向 ContextMenu
中传入 options
以初始化单例构造器:视频
const menuSinglton = ContextMenu({ menus: [ { name: "custom menu 1", onClick: function (e) { console.log("menu1 clicked"); }, }, { name: "custom menu 2", onClick: function (e) { console.log("menu2 clicked"); }, }, { name: "custom menu 3", onClick: function (e) { console.log("menu3 clicked"); }, }, ], });
初始化完成后,即可以经过 menuSinglton.getInstance()
获取菜单实例了。blog
当咱们右击页面时,获取到鼠标的坐标,设置菜单为固定定位(position: fixed
),并将其左上角位置设置为鼠标坐标,以实现菜单在鼠标点击位置的弹出:
function showMenu(e) { const menus = menuSinglton.getInstance(); menus.style.top = `${e.clientY}px`; menus.style.left = `${e.clientX}px`; menus.style.display = "block"; }
最后,当咱们点击页面中的其余区域时须要将菜单隐藏:
function hideMenu(e) { const menus = menuSinglton.getInstance(); menus.style.display = "none"; } document.addEventListener("click", hideMenu);
大功告成!!
本文Demo参考:Codepen Trick by Day (2020-07-05) Custom Context Menus
天天一个小技巧,量变引发质变,但愿你和我一块儿天天多学一点,让技术有趣一点。全部示例将会汇总到个人 tricks-by-day github项目中,欢迎你们莅临指导 😊