当前位置:   article > 正文

Vue实现动态路由【记录学习的快乐】_vue 动态路由

vue 动态路由

1、什么是动态路由
2、动态路由的好处
3、动态路由如何实现

1、什么是动态路由?

动态路由,动态即不是写死的,是可变的。我们可以根据自己不同的需求加载不同的路由,做到不同的实现及页面的渲染。动态的路由存储可分为两种,一种是将路由存储到前端。另一种则是将路由存储到数据库。动态路由的使用一般结合角色权限控制一起使用。

总结:

1:路由可变,不是写死的,动态加载;

2:存储分两种:存储前端、存储数据库

2、动态路由的好处

使用动态路由可以跟灵活,无需手工维护,我们可以使用一个页面对路由进行维护。如果将路由存储到数据库,还可以增加安全性。

总结:

1:灵活,无需手工维护;

2:增加安全性

3、动态路由如何实现

在此以路由存储在数据库为例
流程:一般我们在登录的时候,根据登录用户的角色返回此角色可以访问的页面的路由,前端将路由存储到vuex(vuex存储的数据必须可持久的,不要一刷新页面就不见),我们在路由前置守卫处动态添加拿到的路由,对页面进行渲染。

1)此为我的router目录,index.js对路由添加,守卫拦截等处理。static-route.js为前端定义的静态路由,不需要动态加载的,如登陆页面,忘记密码页面,404页面等。

index.js文件

  1. import Vue from 'vue'
  2. import $cookies from 'vue-cookies'
  3. import VueRouter from 'vue-router'
  4. import store from '../store'
  5. import staticRoute from './static-route.js'​​​
  6. Vue.use(VueRouter)​​
  7. const router = new VueRouter({
  8. mode: 'history',
  9. base: process.env.BASE_URL,
  10. routes: staticRoute //staticRoute为静态路由,不需动态添加
  11. })​
  12. let isToken = true
  13. router.beforeEach(async (to, from, next) => {
  14. //定义isToken为true和vuex不为空时添加路由
  15. if (isToken && store.state.routers.routers.length != 0) {
  16. //从vuex中获取动态路由
  17. const accessRouteses = await store.state.routers.routers;
  18. //动态路由循环解析和添加
  19. accessRouteses.forEach(v => {
  20. v.children = routerChildren(v.children);
  21. v.component = routerCom(v.component);
  22. router.addRoute(v); //添加
  23. })
  24. isToken = false //将isToken赋为 false ,否则会一直循环,崩溃
  25. next({
  26. ...to, // next({ ...to })的目的,是保证路由添加完了再进入页面 (可以理解为重进一次)
  27. replace: true, // 重进一次, 不保留重复历史
  28. })​
  29. } else {
  30. if (to.name == null) {
  31. next("/404")
  32. } else {
  33. if (to.meta.title) { //判断是否有标题
  34. document.title = to.meta.title //给相应页面添加标题
  35. }
  36. next()
  37. }​
  38. }​
  39. })​
  40. function routerCom(path) { //对路由的component解析
  41. return (resolve) => require([`@/views/${path}`], resolve);
  42. }​
  43. function routerChildren(children) { //对子路由的component解析
  44. children.forEach(v => {
  45. v.component = routerCom(v.component);
  46. if (v.children != undefined) {
  47. v.children = routerChildren(v.children)
  48. }
  49. })
  50. return children
  51. }​​
  52. export default router​

2)登陆成功后将获取到的动态路由存储到vuex

 vuex—>index.js文件

  1. import Vue from 'vue'
  2. import Vuex from 'vuex'
  3. //数据持久化
  4. import createPersistedState from "vuex-persistedstate";
  5. Vue.use(Vuex)
  6. const routers = {
  7. namespaced: true,
  8. state: () => ({
  9. routers:"",
  10. }),
  11. mutations: {
  12. routers(state, newsdata) {
  13. state.routers = newsdata
  14. },
  15. },
  16. actions: {
  17. routers(context) {
  18. context.commit('routers')
  19. },
  20. },
  21. getters: {
  22. routers(state) {
  23. console.log("getters", state)
  24. return state.routers
  25. },
  26. }
  27. }
  28. const store = new Vuex.Store({
  29. modules: {
  30. routers: routers,
  31. },
  32. // 数据持久化
  33. plugins: [createPersistedState({
  34. //key是存储数据的键名
  35. key: 'routersData',
  36. //paths是存储state中的那些数据,如果是模块下具体的数据需要加上模块名称,如user.token
  37. paths: ["routers.routers"]
  38. })]
  39. })
  40. export default store

我的动态路由模板

  1. //动态路由
  2. const dynamicRoute = [{
  3. "path": "/main",
  4. "name": "main",
  5. "redirect": "/main/index",
  6. "component": "main/main.vue",
  7. "children": [{
  8. "path": "index",
  9. "name": "index",
  10. "component": "index/index.vue",
  11. "meta": {
  12. "name": "index",
  13. "title": "首页",
  14. "icon": "el-icon-location",
  15. "menu":true //true为菜单栏
  16. }
  17. },
  18. {
  19. "path": "Configuration",
  20. "name": "Configuration",
  21. "redirect": "Configuration/route",
  22. "component": "Configuration/index.vue",
  23. "roles": ['developer', "admin"], // developer、admin角色的用户才能访问该页面
  24. "meta": {
  25. "title": "配置",
  26. "icon": "el-icon-location",
  27. "menu":true
  28. },
  29. "children": [{
  30. "path": "route",
  31. "name": "route",
  32. "component": "Configuration/route/index.vue",
  33. "meta": {
  34. "title": "菜单",
  35. "icon": "",
  36. "menu":true
  37. },
  38. }, {
  39. "path": "user",
  40. "name": "user",
  41. "component": "Configuration/user/index.vue",
  42. "meta": {
  43. "title": "用户管理",
  44. "icon": "el-icon-location",
  45. "menu":true
  46. },
  47. },
  48. {
  49. "path": "admin",
  50. "name": "admin",
  51. "component": "Configuration/admin/index.vue",
  52. "meta": {
  53. "title": "管理员管理",
  54. "icon": "",
  55. "menu":true
  56. },
  57. },
  58. {
  59. "path": "userEdit",
  60. "name": "userEdit",
  61. "component": "Configuration/user/user-Edit.vue",
  62. "meta": {
  63. "title": "编辑用户",
  64. "icon": "",
  65. "menu":false
  66. },
  67. },
  68. ]
  69. },
  70. {
  71. "path": "check",
  72. "name": "check",
  73. "redirect": "check/user",
  74. "component": "check/index.vue",
  75. "roles": ['developer', "admin", "check"], // developer、admin角色的用户才能访问该页面
  76. "meta": {
  77. "title": "审核",
  78. "icon": "el-icon-location",
  79. "menu":true
  80. },
  81. "children": [{
  82. "path": "user",
  83. "name": "checkUser",
  84. "component": "check/check-user/index.vue",
  85. "meta": {
  86. "title": "用户实名审核",
  87. "icon": "el-icon-location",
  88. "menu":true
  89. }
  90. },
  91. {
  92. "path": "enterprise",
  93. "name": "checkEnterprise",
  94. "component": "check/check-enterprise/index.vue",
  95. "meta": {
  96. "title": "企业认证审核",
  97. "icon": "el-icon-location",
  98. "menu":true
  99. },
  100. },
  101. {
  102. "path": "checkNormImage",
  103. "name": "checkNormImage",
  104. "component": "check/check-norm-image/index.vue",
  105. "meta": {
  106. "title": "标准照认证审核",
  107. "icon": "el-icon-location",
  108. "menu":true
  109. },
  110. },
  111. {
  112. "path": "checkHiringJobs",
  113. "name": "checkHiringJobs",
  114. "component": "check/check-hiring-Jobs/index.vue",
  115. "meta": {
  116. "title": "求职、招聘认证审核",
  117. "icon": "el-icon-location",
  118. "menu":true
  119. },
  120. }
  121. ]
  122. }
  123. ]
  124. }, ]
  125. export default dynamicRoute

路由界面

讲一讲遇到的坑及注意点

  1. “component”: “check/check-norm-image/index.vue”, 用字符串再在解析,不要像静态路由一样。否则第一次进去可以,刷新就变空白

  2. 此处为重要的一点,直接用next()不行

    1. next({
    2. ...to, // next({ ...to })的目的,是保证路由添加完了再进入页面 (可以理解为重进一次)
    3. replace: true, // 重进一次, 不保留重复历史
    4. })

    3)由于添加完路由还会重复执行一遍路由守卫,所有必须确保不要一直死循环添加路由。否则直接崩溃。这里我用的是isToken变量确保不循环。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/59005
推荐阅读
相关标签
  

闽ICP备14008679号