如何获取Vuex Store状态中对象数组的新旧值?
解决Vuex数组watch时新旧值引用相同的问题
你遇到的这个问题确实是Vue响应式系统的特性——当你在Vuex里**修改(mutate)**数组/对象(比如push、splice、修改属性)时,新旧值会指向同一个引用,因为Vue不会自动保存修改前的副本。下面给你两种实用的解决方案,你可以根据场景选择:
方案一:在Vuex mutation中替换数组(推荐)
这是最符合Vue响应式设计的方式,核心思路是不修改原数组,而是创建新数组替换它。这样Vue能检测到引用变化,watch的新旧值就会是两个不同的数组,自然能拿到各自的内容。
比如你的mutation原来可能是这样修改数组的:
// 不推荐:直接修改原数组 mutations: { ADD_SELL_ORDER(state, newOrder) { state.orderBookSell.push(newOrder); // 直接修改原数组,引用不变 } }
改成替换数组的方式:
// 推荐:创建新数组替换原数组 mutations: { ADD_SELL_ORDER(state, newOrder) { // 用展开运算符创建新数组,添加新元素后赋值 state.orderBookSell = [...state.orderBookSell, newOrder]; // 或者用slice() + concat,效果一样: // state.orderBookSell = state.orderBookSell.concat([newOrder]); }, UPDATE_SELL_ORDER(state, updatedOrder) { // 如果是更新数组里的某个元素,也返回新数组 state.orderBookSell = state.orderBookSell.map(item => { if (item.id === updatedOrder.id) { return {...item, ...updatedOrder}; // 同样替换对象,不修改原对象 } return item; }); } }
这样修改后,你的组件watch代码不需要改动,就能直接拿到正确的newArray和oldArray:
export default { name: 'O1_OrderBook', watch: { '$store.state.orderBookSell': { deep: true, handler (newArray, oldArray) { console.log('新数组:', newArray); console.log('旧数组:', oldArray); // 现在是修改前的数组副本引用 } } }, }
方案二:在组件中手动保存旧值
如果因为性能或其他原因,必须在Vuex里修改原数组,那可以在组件里自己维护旧值的副本。具体步骤是:
- 在组件data里定义一个变量存储旧值
- 开启watch的
immediate: true,初始化时保存初始值 - 在watch handler里,先使用保存的旧值,再更新旧值为当前新值的深拷贝
代码示例:
import _ from 'lodash'; // 可以用lodash的深拷贝,或者自己实现 export default { name: 'O1_OrderBook', data() { return { previousSellBook: [] } }, watch: { '$store.state.orderBookSell': { deep: true, immediate: true, // 初始化时触发一次,保存初始值 handler (newArray) { // 此时previousSellBook就是修改前的旧值 console.log('旧数组:', this.previousSellBook); console.log('新数组:', newArray); // 更新旧值为当前数组的深拷贝,下次触发时用 this.previousSellBook = _.cloneDeep(newArray); // 如果不用lodash,也可以用JSON.parse(JSON.stringify(newArray)),但注意不能处理函数、Symbol等类型 // this.previousSellBook = JSON.parse(JSON.stringify(newArray)); } } }, }
注意:这种方法需要自己处理深拷贝,如果数组里的对象层级比较深,一定要用可靠的深拷贝方式,不然还是会出现引用共享的问题。
内容的提问来源于stack exchange,提问作者Matthew
相关产品推荐
相关产品推荐

