vue3+vue-router+vite實現(xiàn)動態(tài)路由的全過程
什么是動態(tài)路由
什么場景會用到動態(tài)路由
舉一個最常見的例子,比如說我們要開發(fā)一個后臺管理系統(tǒng),一般來說后臺管理系統(tǒng)都會分角色登錄,這個時候也就涉及到了權限,比如說這個后臺管理系統(tǒng)現(xiàn)在有超級管理員,管理員,運維,財務等這幾個角色,每個角色登錄系統(tǒng)之后都會有不同的權限,超級管理員需要所有的權限,財務可能只需要財務相關的模塊(菜單)以及按鈕等,通常實現(xiàn)這種需求會有以下常見方案
路由表由前端去維護
也就是說我們已知這幾個角色分別對應哪些權限,前端寫好路由配置表,,后端只需要告訴你當前登錄人是屬于哪個角色,前端根據(jù)角色類型去寫一個過濾函數(shù),獲取該角色所擁有的菜單以及按鈕,然后動態(tài)的去添加路由,這樣做有一個缺點就是,如果又增加了一個新的角色怎么辦?某個角色想增加一些權限怎么辦?這個時候前端就需要去新增或者修改代碼,一點也不友好
路由表的數(shù)據(jù)由后端返回
這種也是常用的一種方式,可能我們的系統(tǒng)里面需要開發(fā)一些功能,如菜單管理
,角色管理
,用戶管理
等,也就是常說的權限中心,前端開發(fā)完的頁面所對應的路由信息有后端去維護,這個時候我們在開發(fā)的時候需要約束某一種規(guī)則,比如所有頁面都放到/src/views
目標下面,然后通過菜單管理去維護數(shù)據(jù),維護完的數(shù)據(jù)可以到角色管理里面去配置角色菜單,配置完角色,可以到用戶管理里面給某個用戶配置角色等一些列流程,這樣的話即使新增一個角色,或者修改一個角色的角色菜單,前端都不需要去修改代碼,只要在菜單管理里面維護好了數(shù)據(jù),想怎么改怎么改,后端返回的數(shù)據(jù)格式可能如下:
[ { path: "/application", name: "application", component: "Layout", title: "應用管理", show: true, icon: "", children: [ { path: "", name: "application-index", component: "/application/index.vue", }, ], }, { path: "/permission", name: "permission", component: "Layout", title: "權限管理", show: true, icon: "", children: [ { path: "menu", name: "permission-menu", component: "/permission/menu/index.vue", title: "菜單管理", show: true, icon: "", }, { path: "user", name: "permission-user", component: "/permission/user/index.vue", title: "用戶管理", show: true, icon: "", }, { path: "role", name: "permission-role", component: "/permission/role/index.vue", title: "角色管理", show: true, icon: "", }, ], }, ]
其實仔細觀察這個數(shù)據(jù)結構,是不是有點熟悉,path
,name
,component
,children
,我們好像手動維護路由表的時候也會用到這些屬性
如何實現(xiàn)動態(tài)路由
實現(xiàn)動態(tài)路由其實就要用到vue-router
提供的一個方法,叫addRoute
在之前版本的時候是addRoutes
,現(xiàn)在非版本的vue-router
給廢除了addRoute()
如何使用呢?可以看一下官方文檔
當我們添加一個主路由
的時候
router.addRoute({ path: '/permission', name: 'permission', component: () => import('xxxxx')})
添加子路由
也就是嵌套路由
router.addRoute('主路由的name', { path: 'settings', component: AdminSettings })
既然我們已經知道了addRoute()
方法如何使用,下面我們就可以去實現(xiàn)這部分邏輯
我們看一下官方文檔的導航守衛(wèi)里面的內容
在之前我們使用導航守衛(wèi)的時候需要一個參數(shù)next()
去控制是否放行以及去哪個頁面,但是在新版本的vue-router
里面可以不是用next()
,當然你是用也行~
我們可以新建一個permission.ts
文件
import router from "./index"; import { useSessionStorage } from "@vueuse/core"; import { StorageEnum } from "@/enum"; import { useUserStore } from "@/store"; const whiteList = ["/login", "/404"]; router.beforeEach(async (to) => { const token = useSessionStorage(StorageEnum.TOKEN, "").value; // 如果在白名單里面 并且 token 不存在 if (whiteList.includes(to.path) && !token) { return true; } else { const { menuList, getMenuList } = useUserStore(); // 如果為空數(shù)組,name就請求接口重新獲取后端維護的路由數(shù)據(jù) if (!menuList.length) { await getMenuList(); console.log("獲取全部路由 =>", router.getRoutes()); // 觸發(fā)重定向 不這樣寫會導致刷新找不到路由 兩種寫法都行 // return { path: to.fullPath }; return to.fullPath; } } });
這里我們可以看到一會return true
一會return to.fullpath
是為什么,通過官方導航守衛(wèi)
里面的介紹,我們可以知道的是
通過官方文檔動態(tài)路由
,我們可以直到
所以說return to.fullpath
是官方告訴我們要這么使用,也是為了解決動態(tài)路由
頁面刷新的時候會出現(xiàn)頁面空白
或者404
的問題
出現(xiàn)404的話比如說你在路由表中維護了下面路由映射
{ path: "/:pathMatch(.*)", name: "page404", component: () => import("@/views/system/404.vue"), }
上面說的主要是在全局導航守衛(wèi)
里面的一些使用及注意事項,我們可以看到并沒有用到addRoute()
這個方法,也沒有出現(xiàn)拿到后端數(shù)據(jù)前端轉換成路由表的相關代碼,但是我們可以看到有一個getMenuList()
函數(shù),我們在開發(fā)的時候,肯定是要考慮到復用以及復雜邏輯抽取的問題,一個動態(tài)路由的實現(xiàn)會牽扯到很多知識點接口請求,vuex或者pinia狀態(tài)維護,vue-router,vite里面怎么獲取文件等
下面看一下如何獲取到接口給的數(shù)據(jù),轉換成vue-router能夠識別的數(shù)據(jù)
首先我們要看一個vite官方給提供的功能,我們拿到后端給的文件路徑
如上面代碼出現(xiàn)的component
字段,如/application/index.vue
,這個文件可能在我們本地項目中的src/views/application/index.vue
這個路徑下
我們需要把它轉換成一個下面的格式() => import('xxxx')
,我們需要動態(tài)的去拼接獲取文件,該怎么實現(xiàn)呢?
vite官方文檔中有說明
需要使用import.meta.glob
,這個時候我們可以打印一下import.meta.glob("../views/**")
,看一下返回的到底是什么
返回的是一個對象,而對象的key
我們可以拼接獲取到,而value
正是我們想要的動態(tài)獲取的文件路徑
以下代碼僅供參考,有很多需要完善的地方,只為演示使用
import type { RouterType } from "@/router/type"; import router from "@/router"; import type { RouteRecordRaw } from "vue-router"; export const useRouterConfig = () => { // 獲取views目錄下的所有的文件 不要使用@別名 const modules = import.meta.glob("../views/**"); const asyncRoutes = ref<RouterType[]>([]); const addRoutes = (menus: RouterType[]) => { asyncRoutes.value = menus; filterAsyncRouter(); // 動態(tài)添加 / 路由 router.addRoute({ path: "/", redirect: asyncRoutes.value[0].path, }); }; const filterAsyncRouter = () => { const routerLoop = (routes: RouterType[], ParentName?: string) => { routes.forEach((item) => { if (item.component === "Layout") { item.component = () => import("@/layout/index.vue"); } else { item.component = resolveComponent(item.component); } const { title, show, icon, name, path, component, children } = item; const route: RouteRecordRaw = { component, path, name, meta: { title, show, icon, }, children: children as any, }; // 動態(tài)添加路由 if (ParentName) { router.addRoute(ParentName, route); } else { router.addRoute(route); } if (item.children && item.children.length > 0) { routerLoop(item.children, item.name); } }); }; routerLoop(asyncRoutes.value); }; const resolveComponent = (path: string) => { console.log(modules); // 拿到views下面的所有文件之后,動態(tài)拼接`key`去獲取value const importPage = modules[`../views${path}`]; if (!importPage) { throw new Error( `Unknown page ${path}. Is it located under Pages with a .vue extension?` ); } return importPage; }; return { addRoutes }; };
綜上所述:
要想實現(xiàn)vite+vue-router實現(xiàn)動態(tài)路由我們需要用到
addRoute()
import.meta.glob()
獲取后端tree數(shù)據(jù),遞歸循環(huán),可能業(yè)務會有type類型,比如分為模塊,菜單,頁面,按鈕等,到時候結合業(yè)務去實現(xiàn)邏輯
導航守衛(wèi)使用時的注意事項,否則會出現(xiàn)刷新白屏,或者路由訪問死循環(huán)等
總結
到此這篇關于vue3+vue-router+vite實現(xiàn)動態(tài)路由的文章就介紹到這了,更多相關vue-router+vite動態(tài)路由內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
vue2項目導出操作實現(xiàn)方法(后端接口導出、前端直接做導出)
這篇文章主要給大家介紹了關于vue2項目導出操作實現(xiàn)方法的相關資料,文中介紹的是后端接口導出、前端直接做導出,通過代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考借鑒價值,需要的朋友可以參考下2024-05-05vue 實現(xiàn)LED數(shù)字時鐘效果(開箱即用)
這篇文章主要介紹了vue 實現(xiàn)LED數(shù)字時鐘效果(開箱即用),每一個數(shù)字由七個元素構成,即每一個segment元素,本文給大家分享實現(xiàn)實例,感興趣的朋友一起看看吧2019-12-12vue中formdata傳值給后臺時參數(shù)為空的問題
這篇文章主要介紹了vue中formdata傳值給后臺時參數(shù)為空的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06vue使用WEB自帶TTS實現(xiàn)語音文字互轉的操作方法
這篇文章主要介紹了vue使用WEB自帶TTS實現(xiàn)語音文字互轉,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧2024-01-01