如何利用Vue3+Element?Plus實現(xiàn)動態(tài)標(biāo)簽頁及右鍵菜單
1 前言
1.1 目的
Tabs 動態(tài)標(biāo)簽頁實現(xiàn)右鍵菜單【關(guān)閉當(dāng)前標(biāo)簽頁】、【關(guān)閉左側(cè)標(biāo)簽頁】、【關(guān)閉右側(cè)標(biāo)簽頁】、【關(guān)閉其他標(biāo)簽頁】、【關(guān)閉全部標(biāo)簽頁】功能
1.2 普通右鍵菜單
網(wǎng)上使用比較多的是v-contextmenu
插件實現(xiàn)右鍵菜單,但該插件對于v-for
循環(huán)生成的元素失效,插件內(nèi)部右鍵菜單顯示執(zhí)行的是emit('show')
未傳入當(dāng)前元素節(jié)點(可能后續(xù)會修復(fù)),且樣式需要自行修改
1.3 本文右鍵菜單方式
本文使用element-plus
自帶的el-dropdown
實現(xiàn)右鍵菜單
2 生成動態(tài)標(biāo)簽頁
2.1 準(zhǔn)備變量容器
<script setup lang="ts"> import { ref } from 'vue' interface TabType { title: string //標(biāo)簽頁顯示名稱 componentName: string //動態(tài)組件名 data: any //動態(tài)組件傳參 } interface TabListType extends TabType { name: string //標(biāo)簽頁唯一標(biāo)識,添加標(biāo)簽頁時根據(jù) componentName 自動生成 } const tabList = ref<TabListType[]>([]) //存放標(biāo)簽頁數(shù)組 const tabValue = ref('home') //存放當(dāng)前激活標(biāo)簽頁,默認(rèn)激活首頁 </script>
2.2 構(gòu)造標(biāo)簽頁
- 可動態(tài)添加標(biāo)簽頁
- 除【首頁】外,可動態(tài)移除標(biāo)簽頁
<template> <el-tabs v-model="tabValue" type="card" @tab-remove="removeTab"> <el-tab-pane label="首頁" name="home"> <Home /> </el-tab-pane> <el-tab-pane v-for="item in tabList" :name="item.name" :key="item.name" closable> <component :is="item.componentName" v-bind="item.data"> </component> </el-tab-pane> </el-tabs> </template>
2.3 動態(tài)添加標(biāo)簽頁
const addTab = (tab: TabType) => { //保證相同組件路徑標(biāo)簽頁 name 標(biāo)識唯一 const name = `${tab.componentName}_${Date.now()}` tabList.value.push({ ...tab, name }) tabValue.value = name } addTab({ title: '標(biāo)簽1', componentName: 'tag1', data: { test: '這是測試數(shù)據(jù)' } })
2.4 動態(tài)移除標(biāo)簽頁
const removeTab = (targetName: string) => { const index = tabList.value.findIndex((item) => item.name === targetName) tabList.value.splice(index, 1) //當(dāng)前激活標(biāo)簽頁與觸發(fā)右鍵菜單標(biāo)簽頁是同一頁 if (targetName === tabValue.value) { //當(dāng)前激活標(biāo)簽頁是標(biāo)簽頁數(shù)組的第一個,則將激活標(biāo)簽頁設(shè)置為 home //當(dāng)前激活標(biāo)簽頁不是標(biāo)簽頁數(shù)組的第一個,則將激活標(biāo)簽頁設(shè)置為當(dāng)前激活標(biāo)簽頁的前一頁 tabValue.value = index === 0 ? 'home' : tabList.value[index - 1].name } } removeTab('tag1')
3 生成右鍵菜單
3.1 擴(kuò)展標(biāo)簽頁
<template> <el-tabs v-model="tabValue" type="card" @tab-remove="removeTab"> <el-tab-pane label="首頁" name="home"> <Home /> </el-tab-pane> <el-tab-pane v-for="item in tabList" :name="item.name" :key="item.name" closable> <!-- 右鍵菜單開始:自定義標(biāo)簽頁顯示名稱,保證每個標(biāo)簽頁都能實現(xiàn)右鍵菜單 --> <template #label> <el-dropdown trigger="contextmenu" :id="item.name" @visible-change="handleChange($event, item.name)" ref="dropdownRef" > <span :class="tabValue === item.name ? 'label' : ''">{{ item.title }}</span> <template #dropdown> <el-dropdown-menu> <el-dropdown-item @click="removeTab(item.name)"> <el-icon><Close /></el-icon>關(guān)閉當(dāng)前標(biāo)簽頁 </el-dropdown-item> <el-dropdown-item @click="removeTab(item.name, 'left')" v-if="show(item.name, 'left')" > <el-icon><DArrowLeft /></el-icon>關(guān)閉左側(cè)標(biāo)簽頁 </el-dropdown-item> <el-dropdown-item @click="removeTab(item.name, 'right')" v-if="show(item.name, 'right')" > <el-icon><DArrowRight /></el-icon>關(guān)閉右側(cè)標(biāo)簽頁 </el-dropdown-item> <el-dropdown-item @click="removeTab(item.name, 'other')" v-if="tabList.length > 1" > <el-icon><Operation /></el-icon>關(guān)閉其他標(biāo)簽頁 </el-dropdown-item> <el-dropdown-item @click="removeTab(item.name, 'all')"> <el-icon><Minus /></el-icon>關(guān)閉全部標(biāo)簽頁 </el-dropdown-item> </el-dropdown-menu> </template> </el-dropdown> </template> <!-- 右鍵菜單結(jié)束 --> <component :is="item.componentName" v-bind="item.data"> </component> </el-tab-pane> </el-tabs> </template>
3.2 增加 show 方法
- 觸發(fā)右鍵菜單標(biāo)簽頁為第一個時,不展示【關(guān)閉左側(cè)標(biāo)簽頁】
- 觸發(fā)右鍵菜單標(biāo)簽頁為最后一個時,不展示【關(guān)閉右側(cè)標(biāo)簽頁】
const show = (name: string, type: string) => { const index = tabList.value.findIndex((item) => name === item.name) return type === 'left' ? index !== 0 : index !== tabList.value.length - 1 }
3.3 擴(kuò)展 removeTab 方法
const removeTab = (targetName: string, type?: string) => { const index = tabList.value.findIndex((item) => item.name === targetName) //查找觸發(fā)右鍵菜單所在標(biāo)簽頁index const currentIndex = tabList.value.findIndex((item) => item.name === tabValue.value) //查找當(dāng)前激活標(biāo)簽頁index,存在當(dāng)前激活標(biāo)簽頁與觸發(fā)右鍵菜單標(biāo)簽頁不是同一個的情況 switch (type) { case 'all': //關(guān)閉全部標(biāo)簽頁 tabList.value = [] //清空除【首頁】外所有標(biāo)簽頁 tabValue.value = 'home' //修改標(biāo)簽激活頁 break case 'other': //關(guān)閉其他標(biāo)簽頁 tabList.value = [tabList.value[index]] if (targetName !== tabValue.value) { tabValue.value = targetName } break case 'left': //關(guān)閉左側(cè)標(biāo)簽頁 tabList.value.splice(0, index) if (currentIndex < index) { tabValue.value = targetName } break case 'right': //關(guān)閉右側(cè)標(biāo)簽頁 tabList.value.splice(index + 1) if (currentIndex > index) { tabValue.value = targetName } break default: //默認(rèn)關(guān)閉當(dāng)前標(biāo)簽頁 tabList.value.splice(index, 1) //當(dāng)前激活標(biāo)簽頁與觸發(fā)右鍵菜單標(biāo)簽頁是同一頁 if (targetName === tabValue.value) { //當(dāng)前激活標(biāo)簽頁是標(biāo)簽頁數(shù)組的第一個,則將激活標(biāo)簽頁設(shè)置為 home //當(dāng)前激活標(biāo)簽頁不是標(biāo)簽頁數(shù)組的第一個,則將激活標(biāo)簽頁設(shè)置為當(dāng)前激活標(biāo)簽頁的前一頁 tabValue.value = index === 0 ? 'home' : tabList.value[index - 1].name } break } }
3.4 解決重復(fù)出現(xiàn)菜單問題
當(dāng)連續(xù)在多個標(biāo)簽頁觸發(fā)右鍵時,會出現(xiàn)多個菜單,解決方案為:在觸發(fā)右鍵菜單后,關(guān)閉其他右鍵菜單
const dropdownRef = ref() const handleChange = (visible: boolean, name: string) => { if (!visible) return dropdownRef.value.forEach((item: { id: string; handleClose: () => void }) => { if (item.id === name) return item.handleClose() }) }
3.5 解決自定義標(biāo)簽樣式問題
<style lang="scss" scoped> .label { color: var(--el-color-primary); //激活標(biāo)簽頁高亮 } :deep(.el-tabs__item) { &:hover { span { color: var(--el-color-primary); //鼠標(biāo)移到標(biāo)簽頁高亮 } } .el-dropdown { line-height: inherit; // 統(tǒng)一標(biāo)簽頁顯示名稱行高 } } </style>
總結(jié)
到此這篇關(guān)于如何利用Vue3+Element Plus實現(xiàn)動態(tài)標(biāo)簽頁及右鍵菜單的文章就介紹到這了,更多相關(guān)Vue3 Element Plus動態(tài)標(biāo)簽頁及右鍵菜單內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解.vue文件中style標(biāo)簽的幾個標(biāo)識符
這篇文章主要介紹了詳解.vue文件中style標(biāo)簽的幾個標(biāo)識符,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-07-07詳解vuex中mapState,mapGetters,mapMutations,mapActions的作用
這篇文章主要介紹了vuex中mapState,mapGetters,mapMutations,mapActions的作用,需要的朋友可以參考下2018-04-04vue實現(xiàn)button按鈕的重復(fù)點擊指令方式
這篇文章主要介紹了vue實現(xiàn)button按鈕的重復(fù)點擊指令方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-08-08