vue实现右键菜单(做一个 Vue 右键菜单组件)
取消原生右键事件
在 main.ts 函数中取消浏览器默认右键菜单:
window.oncontextmenu = () => { return false; };组件模板
做一个不同区域右键点击之后不同菜单项的组件 ,创建组件模板:
<!-- ContextMenu --> <div ref="menu" class="l-menu"> <slot /> <Teleport to="#l-menu-container"> <div ref="panel" :id="l-menu__panel__ + milliseconds" :style="{ left: x + px, top: y + px }"> <div ref="head" class="l-menu__head"> <div class="l-menu__title"> <slot name="title" /> </div> <div @click="panel.style.display = none"> <i-ep-close /> </div> </div> <div class="l-menu__main"> <slot name="content" /> </div> </div> </Teleport> </div>模板中使用了 Teleport ,需要把这一块传递到页面中 l-menu-container 元素中去 ,这个元素在 body 下 ,意思是我的右键菜单组件呼出的面板不受父组件的样式影响 ,包括移动的范围限制 、背景颜色等 ,这些继承父元素样式都需要避免 。
组件 setup
需要获取组件模板的一些引用:
// ContextMenu setup const menu = ref<HTMLElement>(); const head = ref<HTMLElement>(); const panel = ref<HTMLElement>(); 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 组件:
<ContextMenu> <div class="item"> hello </div> <template #title>样式设置</template> <template #content> <BoxSetting /> </template> </ContextMenu>实现效果
创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!