vue3-menus

Vue3.0 自定义右键菜单

Vue3.0 原生实现齐全自定义右键菜单组件, 零依赖,可依据可视区域主动调节显示地位,可反对插槽齐全重写每一项菜单

在线演示

  • 残缺菜单性能演示
  • 复制粘贴演示

疾速装置

npm 装置

npm install vue3-menus

yarn add vue3-menus

CDN

<script src="https://unpkg.com/vue3-menus/dist/vue3-menus.umd.min.js">

应用

CDN引入则不须要 app.use(Vue3Menus)

样例中应用的是@ant-design/icons-vue图标与@element-plus/icons图标、图标能够应用html代码传入、也能够通过插槽自定义图标、也能够齐全重写每一项菜单
// 全局注册组件、指令、办法import { createApp } from 'vue';import Menus from 'vue3-menus';import App from './App.vue';const app = createApp(App);app.use(Menus);app.mount('#app');// 单个注册某个,以下三种形式均可在单个文件内应用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); // 只注册组件app.directive('menus', directive); // 只注册指令app.config.globalProperties.$menusEvent = menusEvent; // 只绑定办法app.mount('#app');
<template>  <div style="height: 98vh; width: 100%;" v-menus:left="menus">    <div class="div" v-menus:left="menus">指令形式关上菜单</div>    <div class="div" @click.stop @contextmenu="($event) => $menusEvent($event, menus)">事件形式关上菜单</div>    <div class="div" @click.stop @contextmenu="rightClick">组件形式关上菜单</div>    <vue3-menus v-model:open="isOpen" :event="eventVal" :menus="menus.menus" hasIcon>      <template #icon="{item: {activeIndex}}">{{activeIndex}}</template>      <template #label="{ item: { item } }">插槽:{{ 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: "返回(B)",          tip: 'Alt+向左箭头',          click: () => {            window.history.back(-1);          }        },        {          label: "点击不敞开菜单",          tip: '不敞开菜单',          click: () => {            return false;          }        },        {          label: "后退(F)",          tip: 'Alt+向右箭头',          disabled: true        },        {          label: "从新加载(R)",          tip: 'Ctrl+R',          icon: {            node: SyncOutlined,            option: {              spin: true            }          },          click: () => location.reload(),          divided: true        },        {          label: "另存为(A)...",          tip: 'Ctrl+S'        },        {          label: "打印(P)...",          tip: 'Ctrl+P',          icon: {            node: Printer,            option: {              color: 'red'            }          },          click: () => window.print(),        },        {          label: "投射(C)...",          divided: true        },        {          label: '发送到你的设施',          icon: WindowsOutlined,          children: [            {              label: 'iPhone',            },            {              label: 'iPad'            },            {              label: 'Windows 11'            }          ]        },        {          label: "为此页面创立二维码",          divided: true,          icon: {            node: QrcodeOutlined,            option: {              style: {                color: 'aqua'              }            }          }        },        {          label: "应用网页翻译(F)",          divided: true,          children: [            { label: "翻译成繁体中文" },            { label: "翻译成繁体中文" },            {              label: "百度翻译", children: [                { label: "翻译成繁体中文" },                { label: "翻译成繁体中文" },]            },            {              label: "搜狗翻译", children: [                { label: "翻译成繁体中文" },                { label: "翻译成繁体中文" },              ]            },            {              label: "有道翻译", children: [                { label: "翻译成繁体中文" },                { label: "翻译成繁体中文" },              ]            },          ]        },        {          label: "截取网页(R)"        },        { label: "查看网页源代码(U)", tip: 'Ctrl+U' },        { label: "查看(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;}

指令形式应用

<template>  <div v-menus:left="menus">指令形式关上菜单</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: "返回(B)",          tip: 'Alt+向左箭头',          click: () => {            window.history.back(-1);          }        },        {          label: "点击不敞开菜单",          tip: '不敞开菜单',          click: () => {            return false;          }        }      ]    })    return { menus }  },});</script>

办法形式应用

<template>  <div class="div" @click.stop @contextmenu="rightClick">事件形式关上菜单</div></template><script>import { defineComponent, shallowRef } from "vue";import { menusEvent } from 'vue3-menus';export default defineComponent({  name: "App",  setup() {    const menus = shallowRef({      menus: [        {          label: "返回(B)",          tip: 'Alt+向左箭头',          click: () => {            window.history.back(-1);          }        },        {          label: "点击不敞开菜单",          tip: '不敞开菜单',          click: () => {            return false;          }        }      ]    });    function rightClick(event) {      menusEvent(event, menus.value);      event.preventDefault();    }    return { rightClick }  },});</script>

组件形式应用

<template>  <div class="div" @click.stop @contextmenu="rightClick">组件形式关上菜单</div>  <vue3-menus v-model:open="isOpen" :event="eventVal" :menus="menus" hasIcon>    <template #icon="{item: {activeIndex}}">{{activeIndex}}</template>    <template #label="{ item: { item } }">插槽:{{ 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: "返回(B)",        tip: 'Alt+向左箭头',        click: () => {          window.history.back(-1);        }      },      {        label: "点击不敞开菜单",        tip: '不敞开菜单',        click: () => {          return false;        }      }    ]);    return { menus, isOpen, rightClick, eventVal }  },});</script>

Vite下应用

应用形式1

import { createApp } from 'vue';import App from './App.vue';import Vue3Menus from 'https://esm.sh/vue3-menus@1.0.3'; // 也能够将1.0.3换成其余版本号const app = createApp(App);app.mount('#app');

应用形式2

在vite配置文件vite.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: {      // 其余配置      'vue3-menus': 'https://esm.sh/vue3-menus@1.0.3'// 也能够将1.0.3换成其余版本号    }  }}

参数阐明

单个菜单项参数MenusItemOptions

属性形容类型是否必填默认值
label菜单项名称stringtrue
style每一项菜单的自定义款式objectfalse{}
iconstring: 传入图标html代码、object: 传入组件或者{node: 组件, option: 组件配置参数}string \objectfalseundefined
disabled是否禁用菜单项booleanfalseundefined
divided是否显示分割线booleanfalseundefined
tip没项菜单前面的小提示stringfalse''
click菜单项点击事件,返回nullfalse不敞开菜单Function()falseundefined
children子菜单列表信息MenusItemOptions[]falseundefined

公共参数MenuOptions

属性形容类型是否必填默认值
menus菜单列表信息MenusItemOptions[]true[]
menusStyle菜单容器的款式objectfalse{}
menusItemClass菜单每一项的classstringfalsenull
event鼠标事件信息(指令应用时能够不传)Eventposition必填一项{}
position手动传入菜单显示地位(指令应用时能够不传){x: number, y: number}event必填一项{}
minWidth菜单容器最小宽度number \stringfalsenone
maxWidth菜单容器最打宽度number \stringfalsenone
zIndex菜单层级number \stringfalse3

组件Vue3Menus参数

属性形容类型是否必填默认值插槽传入值
open管制菜单组件显示: v-model:openbooleantruefalsefalse
default默认插槽Slotfalse-activeIndex: 以后选中项, item: 以后菜单属性值
icon图标插槽Slotfalse-activeIndex: 以后选中项, item: 以后菜单属性值
label菜单题目插槽Slotfalse-activeIndex: 以后选中项, item: 以后菜单属性值
suffix菜单后缀插槽Slotfalse-activeIndex: 以后选中项, item: 以后菜单属性值

指令应用配置

指令应用形式形容参数类型参数是否必填默认值
v-menus绑定元素右击关上菜单MenuOptionstrue-
v-menus:all绑定元素左右击均可关上菜单MenuOptionstrue-
v-menus:left绑定元素左击关上MenuOptionstrue-
v-menus:right绑定元素右击关上MenuOptionstrue-