你是否遇到了:

  • addRouter后出现白屏
  • 路由守卫出现死循环

踩了很多坑之后,我终于悟到了vue动态添加路由的正确打开方式;

为了设计权限,在前端我们通常采取两种方式
1、在用户登录时获取该用户权限下的路由表,动态生成路由和菜单栏(后端给定路由)
2、在用户登录时获取用户权限,根据权限筛选出需要的路由(前端通过权限筛选路由)

本篇文章采用方式一

关键点:

  • 使用route中addRouter方法动态添加路由
  • 将路由分为
    (1)动态路由 myRouterObj (可从后端获取)
    (2) 静态路由 staticRoutes 没有权限也可以访问的路由
    注:rootRouter 用来组装动态路由。

router index.js页面

import Vue from 'vue'
import Router from 'vue-router'
import home from '@/pages/Home'
import store from '../store/store'
Vue.use(Router)// 动态路由 模拟后端数据
const myRouterObj = [{path: '/dashboard',name: "dashboard",meta: {title: '系统首页'},component: "Dashboard"},{path: '/table',name: "commonTable",meta: {title: '表格'},component:"CommonTable"},{path: '/calendar',name: "calendar",meta: {title: '日历'},component: "Calendar"}
]// 静态路由 没有权限也可以访问的路由
export const staticRoutes = [{path: "/login",name: "login",component: () => import("@/pages/Login.vue"),}
];// 根路由
const rootRouter = {path: '/',name: 'home',component: home,redirect: '/dashboard',children: []
};export const generatorDynamicRouter = () => {return new Promise((resolve, reject) => {// myRouterObj 这里直接写在页面中了,实际应用中我们需要进行ajax请求获取const routesForHis = generatorForHis(myRouterObj);// routesForHis .push(notFoundRouter);  // 可以定义404nofoun单页面路由rootRouter.children = routesForHis;resolve(rootRouter);});
};export const generatorForHis = (routeMap) => {return routeMap.map(item => {const currentRouter = {path: item.path,// 路由名称,建议唯一name: item.name,// meta: 页面标题, 菜单图标, 页面权限(供指令权限用,可去掉)meta: item.meta,// 该路由对应页面的 组件 (动态加载 @/pages/ 下面的路径文件)component: () => import(`@/pages/` + item.component + '.vue')};// 子菜单,递归处理if (item.children && item.children.length > 0) {currentRouter.children = generatorForHis(item.con);if (currentRouter.children === undefined || currentRouter.children.length <= 0) {delete currentRouter.children;}}return currentRouter;}).filter(item => item);
};// 开始创建路由时
const router = new Router({mode: 'history',base: '/',linkActiveClass: "active",routes: staticRoutes
})router.beforeEach(async (to, from, next) => {var isLogin = store.state.isLogin;if (to.path == "/login") {next()} else {if (isLogin) {if (store.state.allowRouters && store.state.allowRouters.length > 0) {// 路由的出口 判断addRoute是否已经完成 避免路由守卫进入死循环next()} else {const allowRouters = await store.dispatch("GENERATE_ROUTES_DYNAMIC", "aa")if (allowRouters.children.length == 0) {return false;}if (allowRouters) {next({ ...to, replace: true })}return false;}} else {next('/login')}}
})
export default router;

store store.js文件

import Vue from 'vue'
import Vuex from 'vuex'
import { generatorDynamicRouter } from '@/router'
import { default as router, staticRoutes } from '@/router';
Vue.use(Vuex)let isLogin = ''
try {if (localStorage.isLogin) {isLogin = JSON.parse(localStorage.isLogin)}
} catch (e) { }export default new Vuex.Store({state: {isLogin: isLogin,allowRouters: [],},mutations: {login(state) {state.isLogin = true;localStorage.isLogin = true;},SET_ROUTERS(state, data) {state.allowRouters = data;},},actions: {// 产生动态路由GENERATE_ROUTES_DYNAMIC({ commit }, data) {return new Promise(resolve => {generatorDynamicRouter().then((routes) => {const allowRoutes = routes.children || [];// 添加到路由表console.log('allowRoutes: ', allowRoutes);router.addRoute(routes);commit('SET_ROUTERS', allowRoutes);resolve(routes);}).catch(err => {console.error('generatorDynamicRouter', err);});});},}
})

关于next({ ...to, replace: true })的理解
很多人在使用动态添加路由addRoutes()会遇到下面的情况:

  • 问题:在addRoutes()之后,第一次访问被添加的路由会白屏。
  • 原因:在addRoutes()之后,立刻访问被添加的路由时,addRoutes()没有执行结束,因而找不到刚刚被添加的路由导致白屏。
  • 解决方案:需要重新访问一次路由才行。

该如何解决这个问题 ?
此时就要使用next({ ...to, replace: true })来确保addRoutes()时动态添加的路由已经被完全加载上去。

关于next({ …to, replace: true })

  1. replace: true只是一个设置信息,告诉VUE本次操作后,不能通过浏览器后退按钮,返回前一个路由。
  2. next({ ...to })的执行很简单,它会判断:
    如果参数to不能找到对应的路由的话,就再执行一次路由守卫(beforeEach((to, from, next))直到其中的next({ ...to})能找到对应的路由为止。

next({ ...to, replace: true })可以保证addRoutes()已经执行完成,路由中已经有我们后来添加进去的用来路由了。
找到对应的路由之后,接下来将前往对应路由,并执行路由守卫(beforeEach((to, from, next)),因此需要用代码来判断是否可以该入改路由(本文的代码根据store中的allowRoutes的长度是否大于零来确定是否进行next()),如果是,就执行next()放行。

如果守卫中没有正确的放行出口的话,会一直next({ ...to})进入死循环 !!!

因此你还需要确保在当addRoutes()已经完成时,所执行到的这一次路由守卫beforeEach((to, from, next)中有一个正确的next()方向出口。

以下就是上述内容的伪代码,敲重点

if (store.state.allowRouters && store.state.allowRouters.length > 0) {// 路由的出口 addRoute已经完成 避免路由守卫进入死循环next()
}
else{router.addRoute('要添加的路由');// 保证addRoute已经完成,并导航到对应的路由next({ ...to, replace: true })
}

vue动态添加路由之避坑指南相关推荐

  1. vue 动态添加路由

    为什么80%的码农都做不了架构师?>>>    最近在研究权限的相关东西,自然动态加载路由信息少不了.接下来我就来专门记录下我研究的东西. 1.首先后端代码返回一个对象,用java写 ...

  2. vue的动态路由(登录之后拿到动态路由通过addRouters()动态添加路由)

    登录后我们拿到路由动态路由,后端传的数据可能为这个 {path: '/index',meta: {title: '首页',icon: 'icon-shouye',tab_index: 0, //给头部 ...

  3. vue当中addRoutes动态添加路由白屏解决和next(),next(“/“)的一些区别

    问题产生前言 使用动态添加路由router.addRoutes()后进入一个页面,对着这一个页面刷新一下,然后页面就白屏了并且不管刷新多少次都没有用,依旧是白屏,只有重新进入页面才有效果 比如对于网站 ...

  4. UNI-APP/VUE 项目集成 微信SDK /微信开放标签 教程和避坑指南(下)——微信开放标签篇

    UNI-APP/VUE 项目集成 微信开放标签 教程和避坑指南 文章同步发布于

  5. 【前端】Vue+Element UI案例:通用后台管理系统-登陆不同用户显示不同菜单、动态添加路由

    文章目录 目标 代码 0.动态地显示菜单:store 1.动态注册路由 2.解决刷新后摆平问题 总代码 本篇修改的代码文件 tab.js 参考视频: VUE项目,VUE项目实战,vue后台管理系统,前 ...

  6. UNI-APP/VUE 项目集成 微信SDK /微信开放标签 教程和避坑指南

    UNI-APP/VUE 项目集成微信SDK教程和避坑指南 文章同步发布于

  7. ext列表禁止滑动_后台列表设计避坑指南(下)

    编辑导语:列表页是后台界面的重要组成之一,上篇说了后台列表设计的"搜索"设计(详情见:后台列表设计避坑指南 上):本篇继续讲剩下的两个部分的"坑"和必坑指南,我 ...

  8. FlyFish|前端数据可视化开发避坑指南(二)

    FlyFish是云智慧开源的一款数据可视化编排平台.通过配置数据模型为用户提供上百种可视化图形组件,零编码即可实现符合自己业务需求的炫酷可视化大屏. 同时,FlyFish也提供了灵活的拓展能力,支持组 ...

  9. Redis分片代理twemproxy快速搭建 | twemproxy Demo | twitter/ twemproxy 避坑指南 | autoconf-2.69下载

    前言 1.代理分类 面对高可用.高扩展.易维护,用一款redis代理都是上佳的选择. redis代理主要有:predixy.twemproxy.codis.redis-cerberus. 2.性能优劣 ...

最新文章

  1. H - Cow Contest POJ - 3660(Floyd 传递闭包)
  2. Java语言程序设计(基础篇) 第十章 面向对象思考
  3. 了解c语言程序员(工程师)岗位需要掌握哪些能力?_码畜,码农,码皇,程序员有什么区别?...
  4. 轻舟智航发布Driven-by-QCraft第三代自动驾驶硬件方案
  5. WCF 调用webservice
  6. iPhone4 FaceTime 联通官方教程
  7. 今天你们表现的真棒!!!
  8. 域名平台SSL证书及Nginx 配置SSL证书简易教程
  9. 如何查看Tomcat版本信息
  10. Activiti实现流程定义的控制与修改
  11. 【R】 Error in is.data.frame(x) : (list) object cannot be coerced to type 'double'
  12. YAWL工作流软件的介绍和使用
  13. 图像处理基础知识——图片存储形式、色域、图片文件格式
  14. python正态分布函数_数学之美_正态分布(Python代码)
  15. 51单片机 AT24C02 PROTEUS 读写程序 源码
  16. Day06-Python文件和数据格式化
  17. java怎样投简历 面试成功率高_java程序员们什么时候投递简历成功率最高?这是一个细致活!...
  18. 采油厂污水选用流量计的类型建议
  19. WIN10系统休眠文件与保留存储
  20. MySQL,刷题之对视图操作,题+代码!!

热门文章

  1. 不回头的人最勇敢,对自己多点热爱吧
  2. 第一天 HTML基础标签(上)
  3. 动态网页的信息爬取(Python+Selenium)
  4. 在url中取ip或者键值对、手机号脱敏、电话号脱敏、身份证脱敏、银行卡号脱敏、身份证校验
  5. 2021春计算机系统大作业
  6. 人是怎么把天聊死的(引以为鉴)
  7. 组网技术:TP-Link无线路由器设置图解
  8. python语言input和if else的嵌套使用_Python中if语句嵌套的方法
  9. RecyclerView问题:java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adap
  10. 设置和使用苹果 MagSafe 充电器的方法