关于前端:Vue30实现原生高度可自定义菜单组件vue3menus

9次阅读

共计 6259 个字符,预计需要花费 16 分钟才能阅读完成。

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 菜单项名称 string true
style 每一项菜单的自定义款式 object false {}
icon string: 传入图标 html 代码、object: 传入组件或者{node: 组件, option: 组件配置参数} string \ object false undefined
disabled 是否禁用菜单项 boolean false undefined
divided 是否显示分割线 boolean false undefined
tip 没项菜单前面的小提示 string false ''
click 菜单项点击事件,返回 nullfalse不敞开菜单 Function() false undefined
children 子菜单列表信息 MenusItemOptions[] false undefined

公共参数MenuOptions

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

组件 Vue3Menus 参数

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

指令应用配置

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

正文完
 0