我有以下代码:
const routes = [
{ path: '/', component: FooView },
{ path: '/bar', component: BarView }
];
const router = new VueRouter({
routes
});
router.beforeEach(function(to, from, next) {
if (to.path === '/bar') {
next('/');
}
next();
});
如果我省略了太多而你需要查看与路由器相关的其他代码,请告诉我,以便我可以填写。
如果我打开一个新标签并导航到'/#/ bar',我已成功重定向到'/#'。但是,如果我然后进入地址栏并手动添加'/#/ bar'然后按回车键我不会被重定向。如果我再次按地址栏中的Enter键,则我重定向。
我已经逐步完成了控制台中的代码,我发现它正在调用next('/')
,我在push('/')
内看到它调用next('/')
的位置,但它没有生效直到我第二次在地址栏中输入。
我尝试过使用router.replace('/')
,但行为是一样的。我尝试在个别路线上使用beforeEnter
,但行为也相同。
我发现讨论类似行为的两个链接是:https://github.com/vuejs/vue-router/issues/748和https://forum.vuejs.org/t/router-beforeeach-if-manually-input-adress-in-browser-it-does-not-work/12461/2,但都没有帮助我。
有人能解释一下吗?我正在尝试做什么和vue-router提供什么功能之间是否存在脱节?如果不期望这种行为,有人可以提出解决方案吗?
答案 0 :(得分:1)
在vue-router官方文档中,不建议您实现beforeEach()的方式。这是文档所说的:
请确保在通过导航保护的任何给定遍历中,将完全调用一次下一个函数。它可以出现多次,但前提是逻辑路径没有重叠,否则挂钩将永远无法解决或产生错误。如果未通过身份验证,下面是将用户重定向到/ login的示例:
// BAD
router.beforeEach((to, from, next) => {
if (!isAuthenticated) next('/login')
// if the user is not authenticated, `next` is called twice
next()
})
// GOOD
router.beforeEach((to, from, next) => {
if (!isAuthenticated) next('/login')
else next()
})
不确定第一个例子为什么不好,因为两个示例代码在逻辑上应该完全相同。第一次使用next('/')重定向路径时,我的代码弹出错误,但是重新路由仍然成功。寻找专业人士的答案。
答案 1 :(得分:0)
没有太兴奋(还有很多测试要做),似乎我设法解决了我的问题。
而不是:
router.beforeEach(function(to, from, next) {
if (to.path === '/bar') {
next('/');
}
next();
});
我将代码更改为以下内容:
router.beforeEach(function(to, from, next) {
if (to.path === '/bar') {
next('/');
return;
}
next();
});
请注意if语句中添加的return;
。
我仍然对这种行为有疑问。特别是我需要更深入地研究为什么有时它会碰到路线,唯一的区别在于它是第一次还是第二次将URL输入到地址栏中。我确信潜入next
会更深入地回答我的问题。
无论如何,添加return;
会将其变成非阻止者。
答案 2 :(得分:0)
正如其他答案所提到的,next()
函数应该在同一个警卫程序内恰好被调用一次。
重要的是至少要调用一次,否则警卫将永远无法完成并阻止导航。
取自docs->
确保在任何给定的通过导航保护的过程中,将仅一次调用下一个函数。它可以出现多次,但前提是逻辑路径没有重叠,否则挂钩将永远无法解决或产生错误
next()
函数表示此防护已完成,可以调用下一个防护。
通过这样做,可以创建仅在调用next()函数时完成的异步防护。
但是防护罩中的其余代码仍会执行。
这意味着,如果多次调用next()
,将会导致无法预测的行为。
// This will work
if(condition){
next();
}
else{
next();
}
// This cause you pain!
next();
next();
// This aborts the current navigation and "stays" on the same route
next(false)
// These navigate to a different route than specified in the 'to' parameter
next('/');
next({path: '/'})
next({path: '/', query: {urlParam: 'value'}}) // or any option used in router.push -> https://router.vuejs.org/api/#router-forward
// If the argument passed to next is an instance of Error,
// the navigation will be aborted and the error
// will be passed to callbacks registered via router.onError().
next(new Error('message'))