vue3-menus
Vue3.0 customize right-click menu
Vue3.0 native implementation, fully customized right-click menu components, zero dependency, can automatically adjust the display position according to the visual area, and can support the slot to completely rewrite each menu
Project address
Online demonstration
express setup
npm installation
npm install vue3-menus
or
yarn add vue3-menus
CDN
<script src="https://unpkg.com/vue3-menus/dist/vue3-menus.umd.min.js">
use
App is not required for CDN introduction use(Vue3Menus)
The @ Ant Design / icons Vue and @ element plus / icons icons icons are used in the sample. The icons can be passed in using html code, customized through slots, or completely rewritten each menu
// Global registration components, instructions and methods import { createApp } from 'vue'; import Menus from 'vue3-menus'; import App from './App.vue'; const app = createApp(App); app.use(Menus); app.mount('#app'); // To register a single file, the following three methods can be used in a single file import { createApp } from 'vue'; import { directive, menusEvent, Vue3Menus } from 'vue3-menus'; import App from './App.vue'; const app = createApp(App); app.component('vue3-menus', Vue3Menus); // Register components only app.directive('menus', directive); // Register instruction only app.config.globalProperties.$menusEvent = menusEvent; // Bind method only app.mount('#app');
<template> <div style="height: 98vh; width: 100%;" v-menus:left="menus"> <div class="div" v-menus:left="menus">Command mode open menu</div> <div class="div" @click.stop @contextmenu="($event) => $menusEvent($event, menus)">Event mode open menu</div> <div class="div" @click.stop @contextmenu="rightClick">Open menu in component mode</div> <vue3-menus v-model:open="isOpen" :event="eventVal" :menus="menus.menus" hasIcon> <template #icon="{item: {activeIndex}}">{{activeIndex}}</template> <template #Label = "{item: {item}}" > slot: {item. Label} < / template > </vue3-menus> </div> </template> <script> import { defineComponent, nextTick, ref, shallowRef } from "vue"; import { SyncOutlined, WindowsOutlined, QrcodeOutlined } from '@ant-design/icons-vue'; import { Printer } from '@element-plus/icons' export default defineComponent({ name: "App", setup() { const isOpen = ref(false); const eventVal = ref({}); function rightClick(event) { isOpen.value = false; nextTick(() => { eventVal.value = event; isOpen.value = true; }) event.preventDefault(); } const menus = shallowRef({ menus: [ { label: "return(B)", tip: 'Alt+Left Arrow ', click: () => { window.history.back(-1); } }, { label: "Click do not close menu", tip: 'Do not close menu', click: () => { return false; } }, { label: "forward(F)", tip: 'Alt+right arrow ', disabled: true }, { label: "Reload(R)", tip: 'Ctrl+R', icon: { node: SyncOutlined, option: { spin: true } }, click: () => location.reload(), divided: true }, { label: "Save as(A)...", tip: 'Ctrl+S' }, { label: "Print(P)...", tip: 'Ctrl+P', icon: { node: Printer, option: { color: 'red' } }, click: () => window.print(), }, { label: "project(C)...", divided: true }, { label: 'Send to your device', icon: WindowsOutlined, children: [ { label: 'iPhone', }, { label: 'iPad' }, { label: 'Windows 11' } ] }, { label: "Create a QR code for this page", divided: true, icon: { node: QrcodeOutlined, option: { style: { color: 'aqua' } } } }, { label: "Use web translation(F)", divided: true, children: [ { label: "Translate into traditional Chinese" }, { label: "Translate into traditional Chinese" }, { label: "Baidu Translate", children: [ { label: "Translate into traditional Chinese" }, { label: "Translate into traditional Chinese" },] }, { label: "Sogou translation", children: [ { label: "Translate into traditional Chinese" }, { label: "Translate into traditional Chinese" }, ] }, { label: "Youdao translation", children: [ { label: "Translate into traditional Chinese" }, { label: "Translate into traditional Chinese" }, ] }, ] }, { label: "Intercept web pages(R)" }, { label: "View web page source code(U)", tip: 'Ctrl+U' }, { label: "inspect(N)", tip: 'Ctrl+Shift+I' } ] }) return { menus, isOpen, rightClick, eventVal } }, }); </script>
.div { display: inline-block; background-color: aqua; margin: 0 20px; line-height: 200px; padding: 0 20px; height: 200px; }
Instruction mode use
<template> <div v-menus:left="menus">Command mode open menu</div> </template> <script> import { defineComponent, shallowRef } from "vue"; import { directive } from 'vue3-menus'; export default defineComponent({ name: "App", directives: { menus: directive }, setup() { const menus = shallowRef({ menus: [ { label: "return(B)", tip: 'Alt+Left Arrow ', click: () => { window.history.back(-1); } }, { label: "Click do not close menu", tip: 'Do not close menu', click: () => { return false; } } ] }) return { menus } }, }); </script>
Method usage
<template> <div class="div" @click.stop @contextmenu="rightClick">Event mode open menu</div> </template> <script> import { defineComponent, shallowRef } from "vue"; import { menusEvent } from 'vue3-menus'; export default defineComponent({ name: "App", setup() { const menus = shallowRef({ menus: [ { label: "return(B)", tip: 'Alt+Left Arrow ', click: () => { window.history.back(-1); } }, { label: "Click do not close menu", tip: 'Do not close menu', click: () => { return false; } } ] }); function rightClick(event) { menusEvent(event, menus.value); event.preventDefault(); } return { rightClick } }, }); </script>
Component mode use
<template> <div class="div" @click.stop @contextmenu="rightClick">Open menu in component mode</div> <vue3-menus v-model:open="isOpen" :event="eventVal" :menus="menus" hasIcon> <template #icon="{item: {activeIndex}}">{{activeIndex}}</template> <template #Label = "{item: {item}}" > slot: {item. Label} < / template > </vue3-menus> </template> <script> import { defineComponent, nextTick, ref, shallowRef } from "vue"; import { Vue3Menus } from 'vue3-menus'; export default defineComponent({ name: "App", components: { Vue3Menus }, setup() { const isOpen = ref(false); const eventVal = ref({}); function rightClick(event) { isOpen.value = false; nextTick(() => { eventVal.value = event; isOpen.value = true; }) event.preventDefault(); } const menus = shallowRef([ { label: "return(B)", tip: 'Alt+Left Arrow ', click: () => { window.history.back(-1); } }, { label: "Click do not close menu", tip: 'Do not close menu', click: () => { return false; } } ]); return { menus, isOpen, rightClick, eventVal } }, }); </script>
Use under Vite
Usage 1
import { createApp } from 'vue'; import App from './App.vue'; import Vue3Menus from 'https://esm.sh/vue3-menus@1.0.3 '; // You can also set 1.0 3 replace with other version number const app = createApp(App); app.mount('#app');
Usage 2
In the vite configuration file vite Alias replacement in config
import { createApp } from 'vue'; import App from './App.vue'; import Vue3Menus from 'vue3-menus'; const app = createApp(App); app.mount('#app');
export default { resolve: { alias: { // Other configurations 'vue3-menus': 'https://esm.sh/vue3-menus@1.0.3 '/ / you can also add 1.0 3 replace with other version number } } }
Parameter description
Single menu item parameter menuitemoptions
attribute | describe | type | Required | Default value |
---|---|---|---|---|
label | Menu item name | string | true | — |
style | Custom styles for each menu item | object | false | {} |
icon | string: pass in icon html code, object: pass in component or {node: component, option: component configuration parameter} | string | object | false | undefined |
disabled | Disable menu item | boolean | false | undefined |
divided | Show split lines | boolean | false | undefined |
tip | There are no tips behind the menu | string | false | '' |
click | The menu item click event returns null or false without closing the menu | Function() | false | undefined |
children | Submenu list information | MenusItemOptions[] | false | undefined |
Public parameter MenuOptions
attribute | describe | type | Required | Default value |
---|---|---|---|---|
menus | Menu list information | MenusItemOptions[] | true | [] |
menusStyle | Style of menu container | object | false | {} |
menusItemClass | class name of each menu item | string | false | null |
event | Mouse event information (instructions can not be transmitted when used) | Event | And position are required | {} |
position | Manually input the menu display position (it can not be transmitted when the command is used) | {x: number, y: number} | And event are required | {} |
minWidth | Minimum width of menu container | number | string | false | none |
maxWidth | Maximum width of menu container | number | string | false | none |
zIndex | Menu level | number | string | false | 3 |
Component Vue3Menus parameters
attribute | describe | type | Required | Default value | Slot incoming value |
---|---|---|---|---|---|
open | Control menu component display: v-model:open | boolean | true | false | false |
default | Default slot | Slot | false | - | activeIndex: currently selected item, item: current menu attribute value |
icon | Icon slot | Slot | false | - | activeIndex: currently selected item, item: current menu attribute value |
label | Menu title slot | Slot | false | - | activeIndex: currently selected item, item: current menu attribute value |
suffix | Menu suffix slot | Slot | false | - | activeIndex: currently selected item, item: current menu attribute value |
Instruction usage configuration
Instruction usage | describe | Parameter type | Is the parameter required | Default value |
---|---|---|---|---|
v-menus | Right click the binding element to open the menu | MenuOptions | true | - |
v-menus:all | Binding elements can be left and right clicked to open the menu | MenuOptions | true | - |
v-menus:left | Binding element left click to open | MenuOptions | true | - |
v-menus:right | Binding element right click to open | MenuOptions | true | - |