Vue Router导航守卫里获取不到最新的路由参数怎么办?
在使用Vue Router的beforeEach守卫时,发现通过to.params.id获取不到最新的路由参数,总是显示上一次的值。比如从商品详情页/product/123跳转到/product/456时,守卫里打印的id还是123。
已经尝试过在守卫里加next()和立即执行console.log,也检查过路由配置没问题。但当直接在组件created钩子用this.$route.params.id却能拿到正确值,这是为什么呢?
router.beforeEach((to, from, next) => {
console.log('守卫里的参数:', to.params.id) // 总是延迟一拍
next()
})
to对象,其实是即将进入的路由的解析结果,但这个解析结果的params不是响应式的,所以有时候会拿不到最新的值。正确的解决办法是:在beforeEach里不要直接用
to.params.id,而是用to.params的响应式版本,可以通过router.app.$route来获取当前最新的$route对象。具体改法如下:这样就能拿到实时的参数了。你也可以理解为
to是当前导航的快照,而$route才是响应式的数据源。如果你以后要封装成插件的话,也可以把这个逻辑封装进去。不过记住一句话:在导航守卫里别直接依赖
to.params.xxx,那玩意儿经常不靠谱。to.params确实可能会出现延迟一拍的情况。原因是因为路由对象在守卫触发时还没有完全更新。常见的解决方案是使用
watch监听$route的变化,而不是单纯依赖beforeEach。不过如果你非要解决守卫里的问题,可以试试把next()改成带参数的形式:这样做的原理是
next回调会在组件真正更新后执行,这时候就能拿到正确的参数了。不过我个人更推荐直接在组件里通过
watch来处理参数变化,会更直观和可靠。毕竟导航守卫本来就不适合做太复杂的事情,容易踩坑。