不同组件调用$store.state.x是否指向Vuex的同一个对象引用?
问题解答
1. 关于this.$store.state.cart的引用特性
- 所有组件访问到的
this.$store.state.cart始终是同一个内存地址的对象,Vuex的state是全局单例的,默认不会给返回值做自动拷贝,你对JS对象引用传递的规则理解正确,但误解了Vuex的设计逻辑,它没有内置访问时自动复制对象的机制。
2. 未提交mutation仍同步更新的原因
- 你在两个组件的
mounted钩子中执行this.cart = this.$store.state.cart时,是直接将组件本地的cart变量指向了Vuex全局state中cart对象的引用,二者完全共享同一块内存数据。 - 你在
incrementQuantity方法中修改商品数量的操作,本质是直接修改了Vuex state的原始对象属性。Vue的响应式系统会监测到该对象的属性变化,所有引用了这个对象的组件视图都会同步刷新,所以导航栏的计数会自动更新。 - Vuex要求必须通过mutation修改state是开发层面的约定,不是JS语言层面的强制限制,仅在开发模式下会抛出警告,不会阻止你直接修改对象属性。
推荐修正方案
方案一:直接通过计算属性读取state(标准用法)
取消在data中声明cart变量,改为在计算属性中直接返回store的state,修改时必须提交mutation:
// 任意用到购物车的组件通用写法 computed: { cart() { return this.$store.state.cart }, cartTotalLength() { return this.cart.items.reduce((acc, curVal) => acc += curVal.quantity, 0) } }, methods: { incrementQuantity(item) { // 先在Vuex中定义对应mutation,再提交修改 this.$store.commit('updateItemQuantity', { id: item.id, num: 1 }) } }
方案二:需要本地临时修改时手动深拷贝
如果需要做临时编辑、确认后才同步到全局,赋值时手动切断引用关联:
mounted() { // 深拷贝生成独立副本,修改不会影响全局state this.cart = JSON.parse(JSON.stringify(this.$store.state.cart)) }
内容的提问来源于stack exchange,提问作者hans
相关产品推荐
相关产品推荐

