Vuex修改数组内对象属性导致mutation过多的最优解决方案咨询
方案推荐与对比
你提到的三种方案没有绝对的通用最佳实践,需要结合项目规模、业务需求决定,但目前行业内使用率最高的是改良后的通用mutation方案,可以完美解决原通用方案无法处理嵌套对象的问题,比另外两种方案适配性更强。
改良通用mutation的实现示例
借助属性路径设置逻辑,不管嵌套多少层的属性都能统一更新,不需要新增额外的mutation:
// 可以自己实现简易的路径set方法,也可以直接用lodash的_.set function setObjectValue(obj, path, value) { const keys = path.split('.') const lastKey = keys.pop() const target = keys.reduce((res, key) => res[key], obj) target[lastKey] = value } const store = { state: { cars: [ {id: 1, color: "blue", brand: 'Benz', engine: { power: 200 }}, {id: 2, color: "blue"}, {id: 3, color: "blue"}, ] }, mutations: { updateCarAttr(state, { carId, attrPath, value }) { const targetCar = state.cars.find(item => item.id === carId) if (!targetCar) return setObjectValue(targetCar, attrPath, value) } }, getters: { allCars(state){ return state.cars; } }, }
使用时直接传入对应属性的路径即可,嵌套属性也能正常更新:
// 修改一级属性color store.commit('updateCarAttr', { carId: 1, attrPath: 'color', value: 'red' }) // 修改嵌套属性engine.power store.commit('updateCarAttr', { carId: 1, attrPath: 'engine.power', value: 250 })
三种原方案的适用场景
- 单属性单独写mutation:仅适合属性固定且数量少于5个的极小项目,优势是可以在每个mutation内单独加参数校验逻辑(比如重量必须大于0),不容易出现非法值,劣势也很明显,属性多了之后mutation数量爆炸,维护成本极高。
- 通用mutation:改良后已经可以覆盖90%以上的业务场景,代码量少维护方便,是中大型项目的首选,也可以在mutation内加全局校验逻辑,比如属性路径不存在时抛出警告,提前排查问题。
- 全量替换对象:仅适合需要做状态快照的场景,比如撤销/重做、变更历史回溯等需求,每次替换生成新对象方便存储快照,普通业务场景用会增加不必要的代码量,正常使用下性能损耗可以忽略,但操作繁琐没有必要。
额外建议
不管选哪种方案,全项目统一规则即可,不要混用多种更新方式,是避免逻辑混乱的核心原则。如果用的是Pinia,还可以直接用$patch方法批量更新属性,灵活度更高。
内容的提问来源于stack exchange,提问作者Felix Eklöf
相关产品推荐
相关产品推荐

