vue-router's beforeEach后卫偶尔表现出奇怪的行为

时间:2018-04-12 19:24:01

标签: javascript vue.js vue-router

我有以下代码:

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/748https://forum.vuejs.org/t/router-beforeeach-if-manually-input-adress-in-browser-it-does-not-work/12461/2,但都没有帮助我。

有人能解释一下吗?我正在尝试做什么和vue-router提供什么功能之间是否存在脱节?如果不期望这种行为,有人可以提出解决方案吗?

3 个答案:

答案 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'))