推入数组的对象与原对象响应式联动问题求助
解决Vuex中推入数组的对象随原对象响应式更新的问题
嘿,这个问题我之前也碰到过,本质是JavaScript引用类型的特性在搞鬼!
你看,当你把state.orderItem直接推入cart数组时,并没有生成一个新的对象,只是把这个对象的内存引用存进了数组里。这就相当于数组里的元素和state.orderItem是同一个“东西”——后续你修改state.orderItem的toppings属性,数组里的对应对象自然会跟着变,因为它们指向的是同一块内存地址。
先看看你这段关键的mutation代码:
// mutations.js export const addToCart = (state) => { state.cart.push(state.orderItem); // 直接推入原对象的引用 }; export const resetToppings = (state) => { state.orderItem.toppings = []; // 修改原对象,数组里的引用同步变化 };
解决方案:创建原对象的副本再推入数组
核心思路就是切断引用关系,给cart数组推入一个和原对象内容相同但独立的新对象。这里有几种常用的实现方式:
1. 扩展运算符(浅拷贝,适合简单对象)
这是最简洁的方式,适合你的orderItem结构(只有基础类型和数组属性):
export const addToCart = (state) => { // 用扩展运算符复制原对象的所有属性,生成新对象 const newOrderItem = { ...state.orderItem }; state.cart.push(newOrderItem); };
2. Object.assign()(浅拷贝,和扩展运算符效果一致)
如果更习惯ES5的写法,可以用这个:
export const addToCart = (state) => { const newOrderItem = Object.assign({}, state.orderItem); state.cart.push(newOrderItem); };
3. 深拷贝(适合嵌套复杂对象)
如果你的orderItem里有多层嵌套的对象(比如toppings是包含对象的数组),浅拷贝就不够用了,这时候可以用JSON.parse(JSON.stringify())(注意:这种方式会忽略函数、Symbol等特殊类型):
export const addToCart = (state) => { const newOrderItem = JSON.parse(JSON.stringify(state.orderItem)); state.cart.push(newOrderItem); };
要是你的项目里已经引入了Lodash,用_.cloneDeep()会更可靠,能处理更多特殊类型:
import _ from 'lodash'; export const addToCart = (state) => { const newOrderItem = _.cloneDeep(state.orderItem); state.cart.push(newOrderItem); };
这样修改之后,推入cart的就是一个完全独立的新对象了,后续执行resetToppings清空原orderItem的toppings时,数组里的对象不会再跟着变化啦。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

