Vue3+Element?Plus實(shí)現(xiàn)動(dòng)態(tài)標(biāo)簽頁(yè)以及右鍵菜單功能
先上圖
只有首頁(yè)的情況

多個(gè)tab頁(yè)的情況

使用el-dropdown綁定右鍵菜單,為每個(gè)tab頁(yè)綁定一個(gè)右鍵
<el-tabs v-model="activeTab" @tab-click="clickTab" type="border-card" class="demo-tabs" closable @edit="removeTab">
<el-tab-pane v-for="(item, index) in tabs" :key="item.path" :label="item.name" :name="item.path">
<template #label>
<el-dropdown :trigger="['contextmenu']" ref="dropdownRef" :id="item.name"
@visible-change="handleChange($event, item.name)">
{{ item.name }}
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="reload(item)" :disabled="handDisabled('reload', item, index)">
<el-icon>
<Refresh />
</el-icon>重新刷新
</el-dropdown-item>
<el-dropdown-item v-if="item.path != '/welcome'" @click="closeMy(item)"
:disabled="handDisabled('closeMy', item, index)">
<el-icon>
<Close />
</el-icon>關(guān)閉當(dāng)前</el-dropdown-item>
<el-dropdown-item v-if="tabs.length > 1" @click="closeOther(item)"
:disabled="handDisabled('closeOther', item, index)">
<el-icon>
<Remove />
</el-icon>關(guān)閉其他</el-dropdown-item>
<el-dropdown-item v-if="tabs.length > 1" @click="closeAll(item)"
:disabled="handDisabled('closeAll', item, index)">
<el-icon>
<Minus />
</el-icon>關(guān)閉全部</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
</el-tab-pane>
<!--路由占位符-->
<router-view></router-view>
</el-tabs>右鍵菜單生效后控制每個(gè)下拉項(xiàng)的禁用與顯示(每一項(xiàng)代表一個(gè)功能)
const handDisabled = (action: string, data: any, index: any) => {
if (action == 'reload') {
return route.path != data.path
}
if (action == 'closeMy') {
return route.path != data.path
}
if (action == 'closeOther') {
return route.path != data.path
}
return false
}每個(gè)右鍵項(xiàng)對(duì)應(yīng)的功能
const reload = (item: any) => {
router.go(0)
}
const closeMy = (item: any) => {
removeTab(item.path)
}
const closeOther = (item: any) => {
const welcome = { name: "歡迎界面", path: "/welcome" }
console.info(item)
tabsSt.setTabs([welcome])
const { name, path } = item
let oldTabs: any = []
tabs.value.forEach((element: any) => {
oldTabs.push(element.path)
});
if (!oldTabs.includes(path)) {
tabs.value.push({ name: name as any, path })
}
}
const closeAll = (item: any) => {
const welcome = { name: "歡迎界面", path: "/welcome", }
tabsSt.setTabs([welcome])
router.push('/welcome')
}控制每次只顯示一個(gè)右鍵
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()
})
}完整代碼
<template>
<el-tabs v-model="activeTab" @tab-click="clickTab" type="border-card" class="demo-tabs" closable @edit="removeTab">
<el-tab-pane v-for="(item, index) in tabs" :key="item.path" :label="item.name" :name="item.path">
<template #label>
<el-dropdown :trigger="['contextmenu']" ref="dropdownRef" :id="item.name"
@visible-change="handleChange($event, item.name)">
{{ item.name }}
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="reload(item)" :disabled="handDisabled('reload', item, index)">
<el-icon>
<Refresh />
</el-icon>重新刷新
</el-dropdown-item>
<el-dropdown-item v-if="item.path != '/welcome'" @click="closeMy(item)"
:disabled="handDisabled('closeMy', item, index)">
<el-icon>
<Close />
</el-icon>關(guān)閉當(dāng)前</el-dropdown-item>
<el-dropdown-item v-if="tabs.length > 1" @click="closeOther(item)"
:disabled="handDisabled('closeOther', item, index)">
<el-icon>
<Remove />
</el-icon>關(guān)閉其他</el-dropdown-item>
<el-dropdown-item v-if="tabs.length > 1" @click="closeAll(item)"
:disabled="handDisabled('closeAll', item, index)">
<el-icon>
<Minus />
</el-icon>關(guān)閉全部</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
</el-tab-pane>
<!--路由占位符-->
<router-view></router-view>
</el-tabs>
</template>
<script lang="ts" setup true>
import { tabsStore } from '@/pinia/tabs';
import { homeStore } from '@/pinia/home';
import { useRoute, useRouter } from 'vue-router';
import { computed, onMounted, reactive, ref, toRef, watch } from 'vue';
import { Close, Minus, Refresh } from '@element-plus/icons-vue';
const router = useRouter();
const route = useRoute();
const tabsSt = tabsStore();
const { active, menus } = homeStore();
//tabs默認(rèn)選項(xiàng)卡
const activeTab = ref(active)
const tabs = computed(() => {
console.info("....初始化tabs")
if (tabsSt.getTabs.length == 1) {
const welcome = { name: "歡迎界面", path: "/welcome", }
tabsSt.setTabs([welcome])
}
return tabsSt.getTabs
})
//設(shè)置tabs選項(xiàng)卡
const setActive = () => {
activeTab.value = route.path;
}
const removeTab = (targetName: any) => {
if (targetName === '/welcome') {
return
}
const tablist = tabs.value
let activeName = activeTab.value;
if (activeName === targetName) {
tablist.forEach((tab: any, index: any) => {
if (tab.path === targetName) {
const nextTab = tablist[index + 1] || tablist[index - 1]
if (nextTab) {
activeName = nextTab.path
}
}
})
}
activeTab.value = activeName
tabsSt.setTabs(tablist.filter((tab: any) => tab.path !== targetName))
router.push({ path: activeName })
}
const clickTab = (tab: any) => {
const { props } = tab
router.push({ path: props.name })
}
const reload = (item: any) => {
router.go(0)
}
const closeMy = (item: any) => {
removeTab(item.path)
}
const closeOther = (item: any) => {
const welcome = { name: "歡迎界面", path: "/welcome" }
console.info(item)
tabsSt.setTabs([welcome])
const { name, path } = item
let oldTabs: any = []
tabs.value.forEach((element: any) => {
oldTabs.push(element.path)
});
if (!oldTabs.includes(path)) {
tabs.value.push({ name: name as any, path })
}
}
const closeAll = (item: any) => {
const welcome = { name: "歡迎界面", path: "/welcome", }
tabsSt.setTabs([welcome])
router.push('/welcome')
}
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()
})
}
const handDisabled = (action: string, data: any, index: any) => {
if (action == 'reload') {
return route.path != data.path
}
if (action == 'closeMy') {
return route.path != data.path
}
if (action == 'closeOther') {
return route.path != data.path
}
return false
}
const addTab = () => {
const { name, path } = route
let oldTabs: any = []
tabs.value.forEach((element: any) => {
oldTabs.push(element.path)
});
if (!oldTabs.includes(path)) {
tabs.value.push({ name: name as any, path })
}
}
watch(() => route.path, () => {
setActive();
addTab();
})
//vuex刷新數(shù)據(jù)丟失
// const beforeRefresh = () => {
// window.addEventListener('beforeunload', () => {
// sessionStorage.setItem("tabsView", JSON.stringify(tabsSt.getTabs))
// })
// let tabSession = sessionStorage.getItem("tabsView")
// if (tabSession) {
// let oldTabs = JSON.parse(tabSession);
// if (oldTabs.length > 0) {
// tabsSt.setTabs(oldTabs)
// }
// }
// }
const beforeRefresh = () => {
window.addEventListener('beforeunload', () => {
console.info("beforeunload...")
})
}
onMounted(() => {
beforeRefresh();
setActive();
})
</script>
<style lang="scss">
.demo-tabs {
// min-height: 100vh;
border: none;
border-radius: 5px;
}
.el-tabs--border-card>.el-tabs__content {
padding: 10px;
}
.el-tabs__item {
font-size: 8px;
font-weight: 1;
padding: 0 8px;
}
</style>總結(jié)
到此這篇關(guān)于Vue3+Element Plus實(shí)現(xiàn)動(dòng)態(tài)標(biāo)簽頁(yè)以及右鍵菜單功能的文章就介紹到這了,更多相關(guān)Vue3動(dòng)態(tài)標(biāo)簽頁(yè)及右鍵菜單內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue如何實(shí)現(xiàn)動(dòng)態(tài)的選中狀態(tài)切換效果
這篇文章主要介紹了vue如何實(shí)現(xiàn)動(dòng)態(tài)的選中狀態(tài)切換效果,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04
vue數(shù)據(jù)響應(yīng)式原理知識(shí)點(diǎn)總結(jié)
在本篇文章里小編給各位整理的是一篇關(guān)于vue數(shù)據(jù)響應(yīng)式原理知識(shí)點(diǎn)總結(jié),有興趣的朋友們可以跟著學(xué)習(xí)下。2020-02-02
vue.js踩坑之ref引用細(xì)節(jié)點(diǎn)講解
這篇文章主要介紹了vue.js踩坑之ref引用細(xì)節(jié)點(diǎn)講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
Vue實(shí)現(xiàn)關(guān)聯(lián)頁(yè)面多級(jí)跳轉(zhuǎn)(頁(yè)面下鉆)功能的完整實(shí)例
這篇文章主要給大家介紹了關(guān)于Vue實(shí)現(xiàn)關(guān)聯(lián)頁(yè)面多級(jí)跳轉(zhuǎn)(頁(yè)面下鉆)功能的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03
Vue?element實(shí)現(xiàn)權(quán)限管理業(yè)務(wù)流程詳解
目前本人再使用vue-element-admin項(xiàng)目時(shí)都是通過(guò)直接刪除一些用不上的路由來(lái)進(jìn)行側(cè)邊欄的清除,但是其實(shí)有一個(gè)更加好的辦法來(lái)對(duì)項(xiàng)目的側(cè)邊欄顯示的內(nèi)用進(jìn)行管理,就是權(quán)限管理,其實(shí)也不知道這個(gè)方法好不好,原理上來(lái)說(shuō)時(shí)跟直接刪除該路由的方式時(shí)一樣的2022-08-08
vue踩坑記之npm?install報(bào)錯(cuò)問(wèn)題解決總結(jié)
當(dāng)你跑起一個(gè)項(xiàng)目的時(shí)候,第一步需要先安裝依賴npm install,下面這篇文章主要給大家介紹了關(guān)于vue踩坑之npm?install報(bào)錯(cuò)問(wèn)題解決的相關(guān)資料,需要的朋友可以參考下2022-06-06
Vue系列:通過(guò)vue-router如何傳遞參數(shù)示例
本篇文章主要介紹了Vue系列:通過(guò)vue-router如何傳遞參數(shù)示例,具有一定的參考價(jià)值,有興趣的可以了解一下。2017-01-01

