Vue3.0 implements the native highly customizable menu component vue3 menu

Posted by webaddict on Sat, 18 Dec 2021 15:36:33 +0100

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 -

Topics: Vue Vue.js css