Vue3封裝實(shí)現(xiàn)右鍵菜單組件
實(shí)現(xiàn)思路
在 Vue 中封裝右鍵菜單組件時(shí),可以通過(guò) addEventListener 監(jiān)聽(tīng) contextmenu 事件,也可以直接在標(biāo)簽上綁定 @contextmenu事件。由于我們?cè)?Vue 中封裝組件,應(yīng)當(dāng)充分利用框架的優(yōu)勢(shì),使用 @contextmenu 語(yǔ)法來(lái)讓代碼更簡(jiǎn)潔和易于維護(hù)。
封裝組件
由于不同區(qū)域需要顯示不同的菜單項(xiàng),因此該組件的菜單項(xiàng)由外部傳入。
defineExpose將變量、方法暴露出去,使得父組件能夠訪問(wèn)這些暴露的內(nèi)容
menu.vue
<template> <div class="menu" v-if="show" ref="menuRef"> <div class="menu-item" v-for="(item, index) in operation" :key="index" @click="handleClick(item.name)" > { { item.name }} </div> </div> </template> <script lang="ts" setup> //友情提示:如果使用的不是naive-ui可以直接將有關(guān)naive-ui的代碼注釋掉 import { useMessage } from 'naive-ui' import { nextTick, ref } from 'vue' //使用naive-ui的消息提示框,要在根組件使用 <n-message-provider></>n-message-provider> let message = useMessage() //點(diǎn)擊菜單項(xiàng) const handleClick = (name) => { message.info(name) show.value = false } // 接收父組件傳入的菜單項(xiàng) defineProps({ operation: { type: Array, default: () => [], }, }) //用來(lái)顯示、隱藏菜單 const show = ref(false) let menuRef = ref() //獲取并設(shè)置菜單的位置 const setPosition = (x, y) => { nextTick(() => { let dom = menuRef.value dom.style.left = x + 'px' dom.style.top = y + 'px' dom.style.height = 'fit-content' let height = dom.style.height dom.style.height = height }) } //暴露數(shù)據(jù) defineExpose({ show, setPosition, }) </script> <style lang="scss" scoped> .menu { width: 100px; padding-top: 10px; padding-bottom: 10px; border-radius: 10px; background: #ffffff; height: 0px; position: absolute; z-index: 1000; .menu-item { font-size: 16px; width: 100%; text-align: center; padding-top: 4px; padding-bottom: 4px; cursor: pointer; transition: 0.5s; } .menu-item:hover { background: #e2e2e2; transition: 0.5s; } } </style>
使用組件
在父組件使用組件 在頁(yè)面中,我們通常會(huì)劃分多個(gè)區(qū)域,右鍵點(diǎn)擊不同的區(qū)域時(shí)展示不同的菜單。在這種情況下,需要在事件處理函數(shù)中阻止瀏覽器的默認(rèn)右鍵菜單彈出。此外,如果區(qū)域內(nèi)嵌套了其他區(qū)域,還需要阻止事件冒泡,確保事件只在當(dāng)前區(qū)域內(nèi)處理,從而避免影響到其他區(qū)域的右鍵菜單。
index.vue
<template> <div class="contextMenu" @click="displayNoneMenu()"> <div class="box-1 box" @contextmenu="handleContextMenu($event, 'operationRef')" > <div class="text">操作區(qū)</div> <Menu ref="operationRef" :operation="operation"></Menu> <div class="box-1-1" @contextmenu.stop="handleContextMenu($event, 'operation2Ref')" > <div class="text">操作分區(qū)</div> <Menu ref="operation2Ref" :operation="operation2"></Menu> </div> </div> <div class="box-2 box" @contextmenu="handleContextMenu($event, 'settingRef')" > <div class="text">設(shè)置區(qū)</div> <Menu ref="settingRef" :operation="setting"></Menu> </div> <div class="box-3 box" @contextmenu="handleContextMenu($event, 'infoRef')"> <div class="text">信息區(qū)</div> <Menu ref="infoRef" :operation="info"></Menu> </div> <div class="box-4 box" @contextmenu="handleContextMenu($event, 'toolRef')"> <div class="text">工具區(qū)</div> <Menu ref="toolRef" :operation="tool"></Menu> </div> </div> </template> <script lang="ts" setup> import Menu from './menu.vue' import { ref } from 'vue' //不同的菜單 let operation = [ { name: '添加', }, { name: '刪除', }, { name: '編輯', }, ] let operation2 = [ { name: '查看詳情', }, { name: '查看用戶', }, ] let setting = [ { name: '修改屬性', }, { name: '更新', }, ] let info = [ { name: '查看日志', }, { name: '顯示數(shù)據(jù)', }, ] let tool = [ { name: '復(fù)制', }, { name: '粘貼', }, { name: '刪除', }, ] // 給子組件綁定ref 獲取組件實(shí)例 let operationRef = ref() let operation2Ref = ref() let settingRef = ref() let infoRef = ref() let toolRef = ref() // 緩存當(dāng)前顯示的菜單 let currentMenuRef = ref() //點(diǎn)擊任何區(qū)域,隱藏菜單 const displayNoneMenu = () => { if (currentMenuRef.value) { currentMenuRef.value.show = false } } //右鍵事件 const handleContextMenu = (e, ref_) => { //阻止瀏覽器默認(rèn)事件 e.preventDefault() if (currentMenuRef.value) { //在顯示下次菜單前,先隱藏上一次的菜單。 currentMenuRef.value.show = false } let menuRef = null switch (ref_) { case 'operationRef': menuRef = operationRef.value break case 'operation2Ref': menuRef = operation2Ref.value break case 'settingRef': menuRef = settingRef.value break case 'infoRef': menuRef = infoRef.value break case 'toolRef': menuRef = toolRef.value break } // 通過(guò)獲取到的組件實(shí)例,設(shè)置菜單的顯示和位置 menuRef.show = true menuRef.setPosition(e.offsetX, e.offsetY) currentMenuRef.value = menuRef } </script> <style lang="scss" scoped> .contextMenu { height: 100%; width: 100%; background: palegreen; border-radius: 10px; display: flex; flex-flow: wrap; .box { position: relative; } .box-1 { width: 40%; height: 40%; background: #25a4bb; .box-1-1 { width: 50%; height: 50%; background: coral; } } .box-2 { width: 60%; height: 40%; background: #cacaca; } .box-3 { width: 60%; height: 60%; background: palevioletred; } .box-4 { width: 40%; height: 60%; background: paleturquoise; } .text { font-weight: 600; font-size: 20px; color: #333333; text-align: center; font-family: 'Avenir', Helvetica, Arial, sans-serif; margin-top: 10px; } } </style>
效果
到此這篇關(guān)于Vue3封裝實(shí)現(xiàn)右鍵菜單組件的文章就介紹到這了,更多相關(guān)Vue3右鍵菜單組件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue中虛擬DOM的簡(jiǎn)單實(shí)現(xiàn)
Vue中的虛擬DOM是通過(guò)JavaScript對(duì)象來(lái)描述真實(shí)DOM結(jié)構(gòu)的一種方式,本文將介紹Vue中虛擬DOM的簡(jiǎn)單實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2023-05-05在vue中高德地圖引入和軌跡的繪制的實(shí)現(xiàn)
這篇文章主要介紹了在vue中高德地圖引入和軌跡的繪制的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10vue跳轉(zhuǎn)同一個(gè)路由參數(shù)不同的問(wèn)題
這篇文章主要介紹了vue跳轉(zhuǎn)同一個(gè)路由參數(shù)不同的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08基于Vue.js 2.0實(shí)現(xiàn)百度搜索框效果
這篇文章主要為大家詳細(xì)介紹了基于Vue.js 2.0實(shí)現(xiàn)百度搜索框效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-09-09如何修改element-ui中tree組件的icon圖標(biāo)(小白都會(huì)的前端技能)
這篇文章主要給大家介紹了關(guān)于如何修改element-ui中tree組件的icon圖標(biāo)的相關(guān)資料,本文介紹的是小白都會(huì)的前端技能,文中通過(guò)代碼以及圖文介紹的非常詳細(xì),需要的朋友可以參考下2024-01-01vue3+ts如何通過(guò)lodash實(shí)現(xiàn)防抖節(jié)流詳解
loadsh是一個(gè)工具庫(kù),我們通常使用loadsh的debounce函數(shù)處理防抖,下面這篇文章主要給大家介紹了關(guān)于vue3+ts如何通過(guò)lodash實(shí)現(xiàn)防抖節(jié)流的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-08-08