vue3自定义右键菜单

1,482 阅读2分钟

需要自定义一个右键菜单

需要自定义一个右键菜单,使用在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>