Vuex深层状态变更最佳实践:是否建议在mutation中修改非state引用状态?
不建议在Vuex mutation中直接修改传入的状态引用(绕过state参数)
答案是不建议——哪怕技术上这种写法能生效(因为JavaScript对象是引用类型,修改传入的item属性会同步到state里),但从Vuex的设计原则、代码可维护性和调试体验来看,这都是非常不好的实践。
具体原因如下:
- 调试追踪失效:Vuex的DevTools依赖mutation中对
state参数的操作来记录状态变更的完整轨迹。如果像changeName2那样直接修改传入的引用,DevTools很可能无法关联这个变更到对应的mutation上,你调试时会看不到这个状态变更的来源,排查问题时会非常头疼。 - 代码可读性&维护性差:Vuex的核心思想之一是集中式状态管理,所有状态变更逻辑都应该清晰地体现在mutation对
state的操作上。直接修改传入的item,其他开发者(甚至几周后的你自己)需要额外去追踪这个item到底来自state的哪个部分,大大增加了理解和维护代码的成本。 - 违背Vuex设计规范:mutation的设计就是要让所有状态变更都通过
state参数来完成,保证变更的可预测性和可追溯性。绕过state直接修改引用,相当于打破了这种规范,让状态变更变得“隐蔽”,久而久之会让你的状态管理变得混乱。
正确的实践方式
如果需要修改state中的嵌套对象/数组元素,推荐像changeName1那样,通过state参数明确访问到目标属性再修改。如果是新增属性(确保响应式),可以用Vue.set或者扩展运算符创建新对象/数组:
mutations: { // 修改已有属性 changeName1 (state, payload) { state.foo[0].name = payload.name }, // 新增属性(保证响应式) addNewProp(state, payload) { // 方式1:用Vue.set Vue.set(state.foo[0], 'age', payload.age) // 方式2:用扩展运算符创建新对象 state.foo[0] = { ...state.foo[0], age: payload.age } } }
内容的提问来源于stack exchange,提问作者Eric Guan
相关产品推荐
相关产品推荐

