VUE 路由守卫 next() next({ ...to, replace true }) next(‘‘) 说明
Posted 程序员超时空
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了VUE 路由守卫 next() next({ ...to, replace true }) next(‘‘) 说明相关的知识,希望对你有一定的参考价值。
最近因为next()
遇到了不少问题,在这里记录一下
首先是路由守卫,是不是感觉简简单单
beforeEach((to, from, next) =>
to // 要去的路由
from // 当前路由
next() // 放行的意思
但是在看别的项目时常常能看到next('/logon') 、 next(to) 或者 next( ...to, replace: true )
这又是啥意思呢
其实在路由守卫中,只有next()
是放行,其他的诸如:next('/logon') 、 next(to) 或者 next( ...to, replace: true )
都不是放行,而是:中断当前导航,执行新的导航
可以这么理解:
next()
是放行,但是如果next()
里有参数的话,next()
就像被重载一样,就有了不同的功能。
而对于上面说的中断当前导航,执行新的导航打个比方:
现在我有一个守卫,在守卫中我使用next('/logon')
,肯定有同学认为是会直接跳转到/logon
路由:
beforeEach((to, from, next) =>
next('/logon')
然而年轻人不讲武德,执行时需要这么看:
beforeEach((to, from, next) =>
beforeEach(('/logon', from, next) =>
beforeEach(('/logon', from, next) =>
beforeEach(('/logon', from, next) =>
beforeEac... // 一直循环下去...... , 因为我们没有使用 next() 放行
如果把这个守卫改一下,当我在地址栏输入/home
时
beforeEach((to, from, next) =>
if(to.path === '/home')
next('/logon')
else
// 如果要去的地方不是 /home , 就放行
next()
我本来要去/home
路由,因此执行了第一次 beforeEach((to, from, next)
但是这个路由守卫中判断了如果要去的地方是'/home'
,就执行next('/logon')
,
所以想要访问/home
可以这么看
beforeEach((to, from, next) =>
beforeEach(('/logon', from, next) =>
next() // 现在要去的地方不是 /home , 因此放行
注意:重点就在这,next('/logon')
不是说直接去/logon
路由,而是中断(不是CPU的那个中断!VUE中的中断就是此时不会执行router.afterEach(() =>
)这一次路由守卫的操作,又进入一次路由守卫,就像嵌套一样,一层路由守卫,然后又是一层路由守卫,此时路由守卫进入到第二层时,to.path
已经不是/home
了,这个时候才执行next()
放行操作。
正以为如此很多人在使用动态添加路由addRoutes()
会遇到下面的情况:
在addRoutes()
之后第一次访问被添加的路由会白屏,这是因为刚刚addRoutes()
就立刻访问被添加的路由,然而此时addRoutes()
没有执行结束,因而找不到刚刚被添加的路由导致白屏。因此需要从新访问一次路由才行。
该如何解决这个问题
此时就要使用next( ...to, replace: true )
来确保addRoutes()
时动态添加的路由已经被完全加载上去。
next( ...to, replace: true )
中的replace: true
只是一个设置信息,告诉VUE本次操作后,不能通过浏览器后退按钮,返回前一个路由。
因此next( ...to, replace: true )
可以写成next( ...to )
,不过你应该不希望用户在addRoutes()
还没有完成的时候,可以点击浏览器回退按钮搞事情吧。
其实next( ...to )
的执行很简单,它会判断:
如果参数to
不能找到对应的路由的话,就再执行一次beforeEach((to, from, next)
直到其中的next( ...to)
能找到对应的路由为止。
也就是说此时addRoutes()
已经完成啦,找到对应的路由之后,接下来将执行前往对应路由的beforeEach((to, from, next)
,因此需要用代码来判断这一次是否就是前往对应路由的beforeEach((to, from, next)
,如果是,就执行next()
放行。
如果守卫中没有正确的放行出口的话,会一直next( ...to)
进入死循环 !!!
因此你还需要确保在当addRoutes()
已经完成时,所执行到的这一次beforeEach((to, from, next)
中有一个正确的next()
方向出口。
因此想实现动态添加路由的操作的话,代码应该是这样的:
router.beforeEach((to, from, next) =>
const token = sessionStorage.getItem('access_token')
// 存在 token 说明已经登录
if (token)
// 登录过就不能访问登录界面,需要中断这一次路由守卫,执行下一次路由守卫,并且下一次守卫的to是主页'
if (to.path === '/login')
next( path: '/' )
// 保存在store中路由不为空则放行 (如果执行了刷新操作,则 store 里的路由为空,此时需要重新添加路由)
if (store.getters.getRoutes.length || to.name != null)
//放行
next()
else
// 将路由添加到 store 中,用来标记已添加动态路由
store.commit('ADD_ROUTER', '需要添加的路由')
router.addRoutes('需要添加的路由')
// 如果 addRoutes 并未完成,路由守卫会一层一层的执行执行,直到 addRoutes 完成,找到对应的路由
next( ...to, replace: true )
else
// 未登录时,注意 :在这里也许你的项目不只有 logon 不需要登录 ,register 等其他不需要登录的页面也需要处理
if (to.path !== '/logon')
next( path: '/logon' )
else
next()
万一还是听不懂,也可以next()
比作Java Filter
里的chain.doFilter(req, resp)
@WebFilter(filterName = "EncodingFilter", urlPatterns = "/*")
public class EncodingFilter implements Filter
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException
// 设置编码
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
chain.doFilter(req, resp); // next()
以上是关于VUE 路由守卫 next() next({ ...to, replace true }) next(‘‘) 说明的主要内容,如果未能解决你的问题,请参考以下文章
VUE 路由守卫 next() / next({ ...to, replace: true }) / next(‘/‘)