1.動態(tài)路由
? ? ? ? 1.因為我們左側(cè)權(quán)限菜單是根據(jù)不同用戶顯示不一樣的 所以我們需要使用動態(tài)路由 來動態(tài)生成右側(cè)路由信息
? ? ? ? ? ? ? ? 在總體布局頁面添加router
<router-view>
是 Vue Router 提供的組件,用于動態(tài)展示匹配到的路由組件內(nèi)容。- 通過在合適的位置放置
<router-view>
,你可以根據(jù)路由路徑動態(tài)地渲染對應(yīng)的組件內(nèi)容。
? ? ? ? ?2.router里面需要添加children?
? ? ? ? ? ? ? ? ? ? 因為我們是多級頁面 之后動態(tài)路由也是多級的 如果這里不提前寫children 之后動態(tài)生成的時候找不到Children
? ? ? ? ?3.做動態(tài)路由是否生成判斷 盡量減少生成次數(shù)
? ? ? ? ??1.在store里面添加全局狀態(tài)
? ? ? ? 4.permission.js
router.beforeEach((to,from,next)=>{
const whiteList=['/login'] // 白名單
let token=store.getters.GET_TOKEN;
let hasRoutes = store.state.hasRoutes;
let menuList = store.getters.GET_MENULIST
if(token){
if(!hasRoutes){
bindRoute(menuList);
store.commit("SER_ROUTES_STATE",true)
//注意這一行代碼 在這一篇文章 詳細(xì)解釋了 如不過寫會刷新白屏
next({ ...to, replace: true })
}else{
next();
}
}else{
if(whiteList.includes(to.path)){
next();
}else{
next("/login");
}
}
})
const bindRoute=(menuList)=>{
let newRoutes = router.options.routes;
menuList.forEach(menu=>{
if(menu.children){
menu.children.forEach(m=>{
let route = menuToRoute(m,menu.name)
if(route){
newRoutes[0].children.push(route);
}
})
}
})
//重新添加到路由
newRoutes.forEach(route=>{
router.addRoute(route)
})
}
const menuToRoute=(menu,parentName)=>{
if(!menu.component){
return null;
}else{
let route={
name:menu.name,
path:menu.path,
meta:{
parentName:parentName
}
}
route.component=()=>import('@/views/'+menu.component+'.vue')
return route
}
}
? ? ? ? 1.menuList是我們在登錄時候得到的 樹形結(jié)構(gòu) 表結(jié)構(gòu)
? ? ? ? ?2.menuToRounte是動態(tài)生成路由? 我們傳入menu和父級名字(因為父級名字之后會用到)
? ? ? ? ? ? ?生成route對象 包括 name? path? 和父級名字?
? ? ? ? ? ? ?component對應(yīng)著目錄結(jié)構(gòu)
? ? ? ? ? 3.生成之后 然后把他們添加到路由里面
? ? ? ?
bindRoute
函數(shù)用于將菜單列表轉(zhuǎn)換為路由配置,并添加到路由實例中。它遍歷菜單列表,并根據(jù)每個菜單項生成對應(yīng)的路由配置,然后將這些路由配置添加到newRoutes
數(shù)組中。最后,通過router.addRoute
方法將所有路由配置添加到路由實例中。
menuToRoute
函數(shù)用于將菜單項轉(zhuǎn)換為路由配置。如果菜單項沒有指定組件,則返回null
;否則,生成一個包含菜單名、路徑和父菜單名的路由配置對象,并設(shè)置組件為異步加載形式。
2.動態(tài)標(biāo)簽頁
????????
?1.store里面添加標(biāo)簽頁數(shù)組 一個是當(dāng)前標(biāo)簽頁 一個是全部打開的
?????????
state: {
hasRoutes: false,
editableTabsValue: '/index',
editableTabs: [
{
title: '首頁',
name: '/index'
}
]
},
???????
ADD_TABS: (state, tab) => {
if (state.editableTabs.findIndex(e => e.name == tab.path) === -1) {
state.editableTabs.push({
title: tab.name,
name: tab.path
})
}
state.editableTabsValue = tab.path
},
RESET_TABS: (state) => {
state.editableTabsValue = '/index',
state.editableTabs = [
{
title: '首頁',
name: '/index'
}
]
},
安全退出時候 調(diào)用RESET_TABS這個方法 清空
if(result.data.code===200){
store.commit("SER_ROUTES_STATE",false)
store.commit("RESET_TABS")
store.dispatch('logout')
}
在menuIndex里面添加 click點擊事件
2.tabIndex具體實現(xiàn)
? ? ? ? 1.關(guān)聯(lián)store里面數(shù)據(jù)
? ? ? ? ? ? ? ? 涉及到路由 使用useRouter
const router = useRouter();
const editableTabsValue = ref(store.state.editableTabsValue)
const editableTabs = ref(store.state.editableTabs)
? ? ? ? ? ? ? ? ?因為我們關(guān)聯(lián)的是store里面的數(shù)據(jù) 所以當(dāng)我們store里面數(shù)據(jù)發(fā)生更改之后 頁面并沒有發(fā)生改變 所以我們需要對數(shù)據(jù)進(jìn)行監(jiān)聽 當(dāng)發(fā)生更改之后 重新賦值
<template>
<!-- 選中-->
<el-tabs
v-model="editableTabsValue"
type="card"
class="demo-tabs"
closable
@tab-remove="removeTab"
@tab-click="clickTab"
>
<!-- 所有tab-->
<el-tab-pane
v-for="item in editableTabs"
:key="item.name"
:label="item.title"
:name="item.name"
>
{{ item.content }}
</el-tab-pane>
</el-tabs>
</template>
<script setup>
import {ref, watch} from 'vue'
import store from '@/store'
import {useRouter} from "vue-router";
const router = useRouter();
const editableTabsValue = ref(store.state.editableTabsValue)
const editableTabs = ref(store.state.editableTabs)
const removeTab = (targetName) => {
const tabs = editableTabs.value
let activeName = editableTabsValue.value
// 這里是Path 使得無法刪除首頁
if(targetName==='/index'){
return
}
if (activeName === targetName) {
tabs.forEach((tab, index) => {
if (tab.name === targetName) {
const nextTab = tabs[index + 1] || tabs[index - 1]
if (nextTab) {
activeName = nextTab.name
}
}
})
}
editableTabsValue.value = activeName
editableTabs.value = tabs.filter((tab) => tab.name !== targetName)
store.state.editableTabsValue = editableTabsValue.value
store.state.editableTabs=editableTabs.value
// 這個獲取的是path
router.push({path:activeName})
}
const refreshTabs =()=>{
editableTabsValue.value=store.state.editableTabsValue;
editableTabs.value=store.state.editableTabs;
}
// 可以拿到標(biāo)簽名稱 可以根據(jù)Name 也可以根據(jù)path
const clickTab =(target)=>{
router.push({name:target.props.label})
}
// 監(jiān)聽變化
watch(store.state,()=>{
refreshTabs();
},{deep:true,immediate:true})
// 深度監(jiān)聽
</script>
<style>
.demo-tabs > .el-tabs__content {
padding: 32px;
color: #6b778c;
font-size: 32px;
font-weight: 600;
}
.el-main{
padding:0px;
}
.el-tabs--card>.el-tabs__header .el-tabs__item.is-active{
background-color: lightgray;
}
.el-tabs{
height:45px
}
</style>
3.動態(tài)面包屑實現(xiàn)
? ? ? ? 面包屑
? ? ? ? ?這里就使用到了我們前面提到的parentName?
? ? ? ? 三個if??
? ? ? ? 如果是父級名字 并且index大于一 顯示并且加 /? 系統(tǒng)管理/
? ? ? ? 如果是最后一個直接顯示? ? ? 角色管理
<template>
<el-icon><HomeFilled /></el-icon>
<el-breadcrumb separator="/">
<el-breadcrumb-item v-for="(item,index) in breadcrumbList" :key="index">
<span class="root" v-if="parentName && index>0">{{parentName}} / </span>
<span class="leaf" v-if="index==breadcrumbList.length-1">{{item.name}}</span>
<span class="root" v-else>{{item.name}}</span>
</el-breadcrumb-item>
</el-breadcrumb>
</template>
<script setup>
import { ref,watch } from 'vue'
import {HomeFilled} from '@element-plus/icons-vue'
import {useRoute} from 'vue-router'
import store from "@/store";
const route=useRoute();
const breadcrumbList=ref([]);
const parentName=ref("")
const initBreadcrumbList=()=>{
breadcrumbList.value=route.matched;
parentName.value=route.meta.parentName;
}
watch(route,()=>{
initBreadcrumbList();
},{deep:true,immediate:true})
</script>
<style lang="scss" scoped>
.leaf{
cursor:text;
}
.root{
color:#666;
font-weight:600;
}
</style>
4.路由與導(dǎo)航動態(tài)綁定實現(xiàn)
? ? ? ? ? ? ?為了防止有人不點擊 直接輸入Url跳轉(zhuǎn)? 首先App.vue里面監(jiān)聽 然后添加標(biāo)簽頁數(shù)據(jù)? 此時標(biāo)簽頁可以動態(tài)變化
import { ref ,watch} from 'vue'
import { useRoute,useRouter } from 'vue-router'
const route=useRoute();
const router=useRouter();
const whitePath=['/login','/index','/']
watch(route,(to,from)=>{
console.log("to"+to.name)
console.log(to.path)
if (whitePath.indexOf(to.path)===-1) {
console.log("to.path="+to.path)
let obj = {
name: to.name,
path: to.path
}
store.commit("ADD_TABS", obj)
}
},{deep:true,immediate:true})
? ? ? ? 修改menu使得菜單欄也可以動態(tài)變化文章來源:http://www.zghlxwxcb.cn/news/detail-541195.html
?文章來源地址http://www.zghlxwxcb.cn/news/detail-541195.html
到了這里,關(guān)于[VUE學(xué)習(xí)]權(quán)限管理系統(tǒng)前端vue實現(xiàn)9-動態(tài)路由,動態(tài)標(biāo)簽頁,動態(tài)面包屑的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!