使用扩展运算符拷贝数组后,computed属性为何仍会修改父组件state?
问题根源
你用[...this.drivers]做的是数组的浅拷贝,仅拷贝了数组的外层结构,数组内部存储的每个driver对象依然和原this.drivers里的对象指向同一个内存引用,你在遍历中直接修改x.points本质上还是修改了原对象,自然会影响父组件的状态。而且因为computed会重复执行,每次都会给原对象的points加一次gainedPoints,就会出现数值不断变大的问题。
解决方案
有两种常用的修改思路,你可以根据实际场景选择:
方案1:不修改原对象,排序时直接计算对比值
不需要提前给对象加points属性,直接在sort的对比函数里实时计算值对比,全程不修改原有对象,完全不会触发原数据变更:
computed: { sortedList() { return [...this.drivers].sort((a, b) => { const aTotal = parseFloat(a.gainedPoints) + parseFloat(a.points) const bTotal = parseFloat(b.gainedPoints) + parseFloat(b.points) return bTotal - aTotal }) } }
如果你的渲染逻辑里需要用到计算后的总points,就用方案2。
方案2:拷贝数组内的对象后再修改
对数组内的每个对象单独做拷贝,修改拷贝后的对象,完全不触及原数据:
computed: { sortedList() { // 先遍历拷贝每个driver对象,再计算总points const processedArray = this.drivers.map(driver => { // 浅拷贝单个driver对象(如果driver里还有嵌套对象就需要换成深拷贝逻辑) const copyDriver = {...driver} copyDriver.points = parseFloat(copyDriver.gainedPoints) + parseFloat(copyDriver.points) return copyDriver }) // 排序拷贝后的数组 return processedArray.sort((a, b) => b.points - a.points) } }
注意:如果你的driver对象内部还有嵌套的对象/数组,上面的
{...driver}还是浅拷贝,需要根据你的数据结构调整拷贝逻辑,数据层级不深的话可以用JSON.parse(JSON.stringify(driver))做简易深拷贝,或者自己实现深拷贝函数。
内容的提问来源于stack exchange,提问作者Kos-Mos
相关产品推荐
相关产品推荐

