如何在Vue组件mounted/created中获取Vuex数据?路由切换后无定时器解决异常
问题1:如何在Vue组件的mounted或created函数中获取Vuex store中的数据?
其实非常直接,有两种常用的方式可以轻松实现:
- 直接访问state/getters:在
created或mounted钩子中,直接通过this.$store访问对应的数据即可,比如:
created() { // 从state中获取数据 this.user = this.$store.state.user; // 从getters中获取处理后的数 this.user = this.$store.getters.user; }
- 使用辅助函数简化代码:如果不想每次都写
this.$store,可以用Vuex提供的mapState或mapGetters辅助函数,先引入:
import { mapState, mapGetters } from 'vuex';
然后在组件的computed选项中做映射:
computed: { // 把state中的user映射为组件的计算属性 ...mapState(['user']), // 把getters中的user映射为组件的计算属性 ...mapGetters(['user']) }
之后在created/mounted里直接用this.user就能拿到数据,而且计算属性会自动响应Vuex数据的变化,非常省心。
问题2:路由切换后mounted中无法获取Vuex数据,不用定时器怎么解决?
先帮你分析下问题根源:你遇到的情况大概率是Vuex中的user数据是异步加载的(比如从后端接口请求),但组件的mounted钩子执行时,异步请求还没完成,所以getters.user还是undefined。定时器能凑效是因为它在轮询等待数据,但确实不是优雅的方案,这里给你几个更合理的解决办法:
方法1:用计算属性自动响应数据变化
这是最推荐的方案!直接把Vuex的getters映射为组件的计算属性,因为计算属性是响应式的,当Vuex中的user数据更新时,计算属性会自动同步,根本不需要手动在mounted里赋值:
import { mapGetters } from 'vuex'; export default { computed: { ...mapGetters(['user']) }, // 之后不管是模板里用{{ user }},还是方法里用this.user,都会自动拿到最新数据 }
不管路由怎么切换,只要Vuex里的user准备好,组件就能立刻获取到,完全不用处理异步时机问题。
方法2:订阅Vuex的状态变化
如果必须在钩子函数里手动处理,可以在组件created时订阅store的mutation变化,当user被更新时再赋值:
created() { // 先尝试获取现有数据 this.user = this.$store.getters.user; // 订阅store的mutation,拿到数据后取消订阅 const unsubscribe = this.$store.subscribe((mutation, state) => { // 这里要替换成你实际更新user的mutation名称,比如'UPDATE_USER' if (mutation.type === 'UPDATE_USER') { this.user = state.user; unsubscribe(); } }); // 组件销毁时记得取消订阅,避免内存泄漏 this.$once('hook:beforeDestroy', unsubscribe); }
方法3:在路由守卫中等待数据加载完成
如果user是进入当前路由必须的前置数据,可以在路由守卫里先完成异步请求,再进入组件:
比如在路由配置里:
const routes = [ { path: '/target-page', component: TargetComponent, beforeEnter: async (to, from, next) => { // 替换成你实际获取user的action名称,比如'fetchUser' await store.dispatch('fetchUser'); next(); } } ];
或者在组件内部的路由守卫:
export default { async beforeRouteEnter(to, from, next) { await this.$store.dispatch('fetchUser'); next(vm => { // 这里可以访问组件实例vm,直接赋值 vm.user = vm.$store.getters.user; }); } }
这样组件执行mounted时,user数据已经加载完成,直接访问就不会有问题了。
内容的提问来源于stack exchange,提问作者Govar
相关产品推荐
相关产品推荐

