取消原生右鍵事件
在 main.ts 函式中取消瀏覽器默認右鍵選單:
window.oncontextmenu = () => {
return false;
};
組件模板
做一個不同區域右鍵點擊之后不同選單項的組件,創建組件模板:
<!-- ContextMenu -->
<div ref="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" >
<div >
<slot name="title" />
</div>
<div @click="panel.style.display = 'none'">
<i-ep-close />
</div>
</div>
<div >
<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 >
hello
</div>
<template #title>樣式設定</template>
<template #content>
<BoxSetting />
</template>
</ContextMenu>
實作效果

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/545250.html
標籤:其他
