Vue 2.6 + VueRouter 3.5中beforeRouteUpdate配合async/await数据不更新问题
问题根因
你代码的直接问题出在<router-view>绑定的:key="$route.path"属性:
- 对于
/path/:id格式的路由,不同id对应的$route.path值完全不同,key值变化会强制触发组件销毁重建 - 该场景下不会触发
beforeRouteUpdate钩子,只会执行beforeRouteEnter,你写在beforeRouteUpdate中的赋值逻辑不会运行,fetchedData自然保持初始值null - 你之前尝试在
beforeRouteUpdate的next回调中操作实例无效,本质也是因为该钩子未被触发
解决方法
直接删除<router-view>上的:key绑定即可。对于同路由不同参数的场景,VueRouter默认会复用组件实例,此时会正常触发beforeRouteUpdate钩子,你编写的赋值逻辑可以正常生效。
如果业务场景确实需要给<router-view>绑定key,可直接删除beforeRouteUpdate相关逻辑,所有数据拉取逻辑统一放在beforeRouteEnter中处理即可。
路由守卫配合异步请求的最佳实践
beforeRouteEnter场景:钩子触发时组件实例尚未创建,无法访问this,异步请求完成后必须通过next的回调参数操作组件实例,参考写法:
async beforeRouteEnter(to, from, next) { const data = await fetchData(to) next(vm => vm.fetchedData = data) }
beforeRouteUpdate场景:钩子触发时组件实例已存在,可以直接访问this,异步请求完成后直接给实例属性赋值,再调用next()即可,不需要走next的回调,参考写法:
async beforeRouteUpdate(to, from, next) { this.fetchedData = await fetchData(to) next() }
- 两种场景下都需要保证
next()在异步逻辑完成后调用,避免页面跳转后数据未加载完成出现空内容 - 如果需要展示加载状态,可在请求发起前给实例添加loading标记,请求完成后关闭即可
内容的提问来源于stack exchange,提问作者Huy Phạm
相关产品推荐
相关产品推荐

