手把手教你vue實現動態路由
1、什麼是動態路由?
動態路由,動態即不是寫死的,是可變的。我們可以根據自己不同的需求加載不同的路由,做到不同的實現及頁面的渲染。動態的路由存儲可分為兩種,一種是將路由存儲到前端。另一種則是將路由存儲到數據庫。動態路由的使用一般結合角色權限控制一起使用。
總結:
1)路由可變,不是寫死的,動態加載
2)存儲分兩種:存前端,存數據庫
2、動態路由的好處
使用動態路由可以跟靈活,無需手工維護,我們可以使用一個頁面對路由進行維護。如果將路由存儲到數據庫,還可以增加安全性。
總結:
1)靈活,無需手工維護
2)增加安全性
3、動態路由如何實現
在此以路由存儲在數據庫為例
流程:一般我們在登錄的時候,根據登錄用戶的角色返回此角色可以訪問的頁面的路由,前端將路由存儲到vuex(vuex存儲的數據必須可持久的,不要一刷新頁面就不見),我們在路由前置守衛處動態添加拿到的路由,對頁面進行渲染。
1)此為我的router目錄,index.js對路由添加,守衛攔截等處理。static-route.js為前端定義的靜態路由,不需要動態加載的,如登陸頁面,忘記密碼頁面,404頁面等。
index.js
import Vue from 'vue' import $cookies from 'vue-cookies' import VueRouter from 'vue-router' import store from '../store' import staticRoute from './static-route.js' Vue.use(VueRouter) const router = new VueRouter({ mode: 'history', base: process.env.BASE_URL, routes: staticRoute //staticRoute為靜態路由,不需動態添加 }) let isToken = true router.beforeEach(async (to, from, next) => { //定義isToken為true和vuex不為空時添加路由 if (isToken && store.state.routers.routers.length != 0) { //從vuex中獲取動態路由 const accessRouteses = await store.state.routers.routers; //動態路由循環解析和添加 accessRouteses.forEach(v => { v.children = routerChildren(v.children); v.component = routerCom(v.component); router.addRoute(v); //添加 }) isToken = false //將isToken賦為 false ,否則會一直循環,崩潰 next({ ...to, // next({ ...to })的目的,是保證路由添加完瞭再進入頁面 (可以理解為重進一次) replace: true, // 重進一次, 不保留重復歷史 }) } else { if (to.name == null) { next("/404") } else { if (to.meta.title) { //判斷是否有標題 document.title = to.meta.title //給相應頁面添加標題 } next() } } }) function routerCom(path) { //對路由的component解析 return (resolve) => require([`@/views/${path}`], resolve); } function routerChildren(children) { //對子路由的component解析 children.forEach(v => { v.component = routerCom(v.component); if (v.children != undefined) { v.children = routerChildren(v.children) } }) return children } export default router
2)登陸成功後將獲取到的動態路由存儲到vuex
vuex—>index.js
import Vue from 'vue' import Vuex from 'vuex' //數據持久化 import createPersistedState from "vuex-persistedstate"; Vue.use(Vuex) const routers = { namespaced: true, state: () => ({ routers:"", }), mutations: { routers(state, newsdata) { state.routers = newsdata }, }, actions: { routers(context) { context.commit('routers') }, }, getters: { routers(state) { console.log("getters", state) return state.routers }, } } const store = new Vuex.Store({ modules: { routers: routers, }, // 數據持久化 plugins: [createPersistedState({ //key是存儲數據的鍵名 key: 'routersData', //paths是存儲state中的那些數據,如果是模塊下具體的數據需要加上模塊名稱,如user.token paths: ["routers.routers"] })] }) export default store
我的動態路由模板
//動態路由 const dynamicRoute = [{ "path": "/main", "name": "main", "redirect": "/main/index", "component": "main/main.vue", "children": [{ "path": "index", "name": "index", "component": "index/index.vue", "meta": { "name": "index", "title": "首頁", "icon": "el-icon-location", "menu":true //true為菜單欄 } }, { "path": "Configuration", "name": "Configuration", "redirect": "Configuration/route", "component": "Configuration/index.vue", "roles": ['developer', "admin"], // developer、admin角色的用戶才能訪問該頁面 "meta": { "title": "配置", "icon": "el-icon-location", "menu":true }, "children": [{ "path": "route", "name": "route", "component": "Configuration/route/index.vue", "meta": { "title": "菜單", "icon": "", "menu":true }, }, { "path": "user", "name": "user", "component": "Configuration/user/index.vue", "meta": { "title": "用戶管理", "icon": "el-icon-location", "menu":true }, }, { "path": "admin", "name": "admin", "component": "Configuration/admin/index.vue", "meta": { "title": "管理員管理", "icon": "", "menu":true }, }, { "path": "userEdit", "name": "userEdit", "component": "Configuration/user/user-Edit.vue", "meta": { "title": "編輯用戶", "icon": "", "menu":false }, }, ] }, { "path": "check", "name": "check", "redirect": "check/user", "component": "check/index.vue", "roles": ['developer', "admin", "check"], // developer、admin角色的用戶才能訪問該頁面 "meta": { "title": "審核", "icon": "el-icon-location", "menu":true }, "children": [{ "path": "user", "name": "checkUser", "component": "check/check-user/index.vue", "meta": { "title": "用戶實名審核", "icon": "el-icon-location", "menu":true } }, { "path": "enterprise", "name": "checkEnterprise", "component": "check/check-enterprise/index.vue", "meta": { "title": "企業認證審核", "icon": "el-icon-location", "menu":true }, }, { "path": "checkNormImage", "name": "checkNormImage", "component": "check/check-norm-image/index.vue", "meta": { "title": "標準照認證審核", "icon": "el-icon-location", "menu":true }, }, { "path": "checkHiringJobs", "name": "checkHiringJobs", "component": "check/check-hiring-Jobs/index.vue", "meta": { "title": "求職、招聘認證審核", "icon": "el-icon-location", "menu":true }, } ] } ] }, ] export default dynamicRoute
路由管理界面(可能有不完善的地方)
講一講遇到的坑及註意點
1)“component”: “check/check-norm-image/index.vue”, 用字符串再在解析,不要像靜態路由一樣。否則第一次進去可以,刷新就變空白
2)此處為重要的一點,直接用next()不行
next({ ...to, // next({ ...to })的目的,是保證路由添加完瞭再進入頁面 (可以理解為重進一次) replace: true, // 重進一次, 不保留重復歷史 })
3)由於添加完路由還會重復執行一遍路由守衛,所有必須確保不要一直死循環添加路由。否則直接崩潰。這裡我用的是isToken變量確保不循環。
總結
到此這篇關於vue實現動態路由的文章就介紹到這瞭,更多相關vue實現動態路由內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- 詳解如何使用Vuex實現Vue後臺管理中的角色鑒權
- vue實現動態路由詳細
- Vue 動態路由的實現詳情
- vue實現el-menu和el-tab聯動的示例代碼
- element實現二級菜單和頂部導航聯動的示例