vue动态添加路由之避坑指南
你是否遇到了:
- 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 })
replace: true
只是一个设置信息,告诉VUE本次操作后,不能通过浏览器后退按钮,返回前一个路由。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动态添加路由之避坑指南相关推荐
- vue 动态添加路由
为什么80%的码农都做不了架构师?>>> 最近在研究权限的相关东西,自然动态加载路由信息少不了.接下来我就来专门记录下我研究的东西. 1.首先后端代码返回一个对象,用java写 ...
- vue的动态路由(登录之后拿到动态路由通过addRouters()动态添加路由)
登录后我们拿到路由动态路由,后端传的数据可能为这个 {path: '/index',meta: {title: '首页',icon: 'icon-shouye',tab_index: 0, //给头部 ...
- vue当中addRoutes动态添加路由白屏解决和next(),next(“/“)的一些区别
问题产生前言 使用动态添加路由router.addRoutes()后进入一个页面,对着这一个页面刷新一下,然后页面就白屏了并且不管刷新多少次都没有用,依旧是白屏,只有重新进入页面才有效果 比如对于网站 ...
- UNI-APP/VUE 项目集成 微信SDK /微信开放标签 教程和避坑指南(下)——微信开放标签篇
UNI-APP/VUE 项目集成 微信开放标签 教程和避坑指南 文章同步发布于
- 【前端】Vue+Element UI案例:通用后台管理系统-登陆不同用户显示不同菜单、动态添加路由
文章目录 目标 代码 0.动态地显示菜单:store 1.动态注册路由 2.解决刷新后摆平问题 总代码 本篇修改的代码文件 tab.js 参考视频: VUE项目,VUE项目实战,vue后台管理系统,前 ...
- UNI-APP/VUE 项目集成 微信SDK /微信开放标签 教程和避坑指南
UNI-APP/VUE 项目集成微信SDK教程和避坑指南 文章同步发布于
- ext列表禁止滑动_后台列表设计避坑指南(下)
编辑导语:列表页是后台界面的重要组成之一,上篇说了后台列表设计的"搜索"设计(详情见:后台列表设计避坑指南 上):本篇继续讲剩下的两个部分的"坑"和必坑指南,我 ...
- FlyFish|前端数据可视化开发避坑指南(二)
FlyFish是云智慧开源的一款数据可视化编排平台.通过配置数据模型为用户提供上百种可视化图形组件,零编码即可实现符合自己业务需求的炫酷可视化大屏. 同时,FlyFish也提供了灵活的拓展能力,支持组 ...
- Redis分片代理twemproxy快速搭建 | twemproxy Demo | twitter/ twemproxy 避坑指南 | autoconf-2.69下载
前言 1.代理分类 面对高可用.高扩展.易维护,用一款redis代理都是上佳的选择. redis代理主要有:predixy.twemproxy.codis.redis-cerberus. 2.性能优劣 ...
最新文章
- H - Cow Contest POJ - 3660(Floyd 传递闭包)
- Java语言程序设计(基础篇) 第十章 面向对象思考
- 了解c语言程序员(工程师)岗位需要掌握哪些能力?_码畜,码农,码皇,程序员有什么区别?...
- 轻舟智航发布Driven-by-QCraft第三代自动驾驶硬件方案
- WCF 调用webservice
- iPhone4 FaceTime 联通官方教程
- 今天你们表现的真棒!!!
- 域名平台SSL证书及Nginx 配置SSL证书简易教程
- 如何查看Tomcat版本信息
- Activiti实现流程定义的控制与修改
- 【R】 Error in is.data.frame(x) : (list) object cannot be coerced to type 'double'
- YAWL工作流软件的介绍和使用
- 图像处理基础知识——图片存储形式、色域、图片文件格式
- python正态分布函数_数学之美_正态分布(Python代码)
- 51单片机 AT24C02 PROTEUS 读写程序 源码
- Day06-Python文件和数据格式化
- java怎样投简历 面试成功率高_java程序员们什么时候投递简历成功率最高?这是一个细致活!...
- 采油厂污水选用流量计的类型建议
- WIN10系统休眠文件与保留存储
- MySQL,刷题之对视图操作,题+代码!!
热门文章
- 不回头的人最勇敢,对自己多点热爱吧
- 第一天 HTML基础标签(上)
- 动态网页的信息爬取(Python+Selenium)
- 在url中取ip或者键值对、手机号脱敏、电话号脱敏、身份证脱敏、银行卡号脱敏、身份证校验
- 2021春计算机系统大作业
- 人是怎么把天聊死的(引以为鉴)
- 组网技术:TP-Link无线路由器设置图解
- python语言input和if else的嵌套使用_Python中if语句嵌套的方法
- RecyclerView问题:java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adap
- 设置和使用苹果 MagSafe 充电器的方法