需要自定义一个右键菜单
需要自定义一个右键菜单,使用在vue3的项目中。有两种方法,使用vue的组件,定义.vue文件,初始化右键菜单。还有一种方式是动态生成菜单。本文采用动态生成菜单的方式。
1 context-menu.js 创建菜单
/** 右键菜单的配置
* options:
* {
* menus:[{
* name: string,
* onClick: Function
* }],
* }
*/
let contextMenu = null;
const ContextMenu = function (options) {
let instance;
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");
if (menu.name === "divider") {
li.classList.add("se-contextmenu-divider");
} else {
const liClass = "se-contextmenu-item";
const liiClass = menu.icon || "";
const shortClass = "se-shortcut";
const shortSpan = menu.shortSpan || "";
li.innerHTML = `<div class="${liClass}"><i class="${liiClass}"></i><span>${menu.name}</span><span class="${shortClass}">${shortSpan}</span></div>`;
li.onclick = menu.onClick;
}
ul.appendChild(li);
}
}
const body = document.querySelector("body");
body.appendChild(ul);
return ul;
}
return {
getInstance: function () {
if (!instance) {
instance = createMenu();
}
return instance;
},
};
};
/**
* 智能写作-文本状态下展示右键菜单,编辑状态下不展示此右键菜单
* @param {*} e
*/
function showMenu(e) {
e.preventDefault();
if (contextMenu) {
const menus = contextMenu.getInstance();
menus.style.top = `${e.clientY}px`;
menus.style.left = `${e.clientX}px`;
menus.classList.remove("hidden");
}
}
function hideMenu(event) {
if (contextMenu) {
const menus = contextMenu.getInstance();
menus.classList.add("hidden");
}
}
function initDomEvent() {
contextMenu = ContextMenu({
menus: [
{
name: "剪贴",
icon: "ce-contextmenu-print",
shortSpan: "⌘ + V",
onClick: function (e) {
console.log("剪贴 clicked");
},
},
{
name: "复制",
icon: "ce-contextmenu-print",
shortSpan: "⌘ + V",
onClick: function (e) {
console.log("复制 clicked");
},
},
{
name: "粘贴",
icon: "ce-contextmenu-print",
shortSpan: "⌘ + V",
onClick: function (e) {
console.log("粘贴 clicked");
},
},
{
name: "全选",
icon: "ce-contextmenu-print",
shortSpan: "⌘ + V",
onClick: function (e) {
console.log("全选 clicked");
},
},
],
});
document.addEventListener("contextmenu", showMenu);
document.addEventListener("click", hideMenu);
}
export { initDomEvent, showMenu, hideMenu };
2 调整菜单样式
.custom-context-menu {
position: fixed;
list-style: none;
z-index: 9999;
padding: 4px;
overflow-x: hidden;
overflow-y: auto;
background: #fff;
box-shadow: 0 2px 12px 0 rgb(56 56 56 / 20%);
border: 1px solid #e2e6ed;
border-radius: 2px;
&.hidden {
display: none;
}
ul {
display: flex;
flex-direction: column;
}
li {
// padding: 8px 12px;
// border-bottom: 1px solid #f0f2f5;
// user-select: none;
// transition: all 0.1s;
min-width: 140px;
padding: 0 32px 0 16px;
height: 30px;
display: flex;
align-items: center;
white-space: nowrap;
box-sizing: border-box;
cursor: pointer;
&:last-child {
border-bottom: none;
}
&:hover {
cursor: pointer;
background-color: #0170fe;
color: #fff;
}
&:active {
background-color: #f0f2f7;
}
}
.se-contextmenu-divider {
background-color: #e2e6ed;
margin: 4px 16px;
height: 1px;
}
.se-contextmenu-item i {
width: 16px;
height: 16px;
vertical-align: middle;
display: inline-block;
background-repeat: no-repeat;
background-size: 100% 100%;
flex-shrink: 0;
margin-right: 8px;
}
.se-contextmenu-print {
background-image: url(/src/views/CanvasEditor/editor/assets/images/print.svg);
}
.se-contextmenu-item span {
max-width: 300px;
font-size: 12px;
color: #3d4757;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.se-contextmenu-item span .se-shortcut {
color: #767c85;
height: 30px;
flex: 1;
text-align: right;
line-height: 30px;
margin-left: 20px;
}
.menu-item__save {
background-image: url("./assets/images/save.svg");
}
}
3 在父组件中引入
import {
initDomEvent,
showMenu,
hideMenu,
} from "@/。。。/context-menu.js";
onMounted(()=>{
initDomEvent();
});
<style lang="less">
@import "./content-menu-style.less";
</style>