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 | 選單項點選事件,返回null 或false 不關閉選單 |
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 |
- |
本作品採用《CC 協議》,轉載必須註明作者和本文連結