取消原生右键事件
在 main.ts 函数中取消浏览器默认右键菜单:
window.oncontextmenu = () => { return false;};
组件模板
做一个不同区域右键点击之后不同菜单项的组件,创建组件模板:
模板中使用了 Teleport
,需要把这一块传递到页面中 l-menu-container
元素中去,这个元素在 body 下,意思是我的右键菜单组件呼出的面板不受父组件的样式影响,包括移动的范围限制、背景颜色等,这些继承父元素样式都需要避免。
组件 setup
需要获取组件模板的一些引用:
// ContextMenu setupconst menu = ref();const head = ref();const panel = ref();const milliseconds = new Date().getMilliseconds();const { x, y } = useDraggable(head);onMounted(() => { menu.value.onmouseup = e => { if (e.button == 2) { const container = document.querySelector("#l-menu-container"); const menuId = container.getAttribute("menu-id"); menuId && (document.getElementById(`l-menu__panel__${menuId}`).style.display = "none"); container.setAttribute("menu-id", `${milliseconds}`); panel.value.style.left = `${e.clientX}px`; panel.value.style.top = `${e.clientY}px`; panel.value.style.display = "block"; } };});
鼠标按下放开事件,判断鼠标是左键还是右键,button 为 2 代表右键,右键点击之后需要移除上一个开启的面板,在 body 下的 #l-menu-container
元素上添加一个记录上一次面板的 id。
实现右键出来之后的菜单面板自由地在窗口中移动,直接借助 VueUse useDraggable
函数:
const { x, y } = useDraggable(head);
得到鼠标移动的 x 和 y 值,通过绑定 style 对 left 和 top 进行设置,就可以实现自由移动。
使用组件
该组件有三个插槽,一个默认插槽,两个具名插槽。具名 content 插槽是菜单内容,默认插槽是能呼出右键菜单面板的区域,哪个区域能呼出就在外面套一层 ContextMenu 组件:
hello 样式设置 实现效果