这里有几个不同的角度。
您的商店中的对象state 将是反应式的,就像在组件data 中一样。将跟踪读取该对象的属性,写入新值将触发依赖关系。这只是 Vue 反应性系统在做它的事情。从反应性的角度来看,商店并没有真正参与。
因此,正如您所观察到的,您可以更新反应对象的属性,并且一切似乎都更新得很好。
道具也有类似的现象。子组件不应更改 prop 值,如果他们尝试,则会出现警告消息。但是,如果 prop 值是一个响应式对象,那么该对象的属性可以更改,并且一切看起来都可以正常工作。
那么问题出在哪里?
有一个适用于这两种情况的指导原则。数据只能由其所有者更新。在商店案例中,所有者是商店或商店模块。对于 props,所有者是向下传递数据的上游组件。
为什么?
如果只有所有者更改数据,则更易于维护。如果该责任分散在多个地方,那么将来调试或更改将更加困难。特别是,查找存储突变的所有用法通常非常容易,而尝试查找更新具有通用名称的属性(例如 name)的任何地方可能非常困难。
此外,这里假设对象是“根”数据。如果您后来决定应该在计算属性或存储 getter 中创建此对象,而不是直接在数据/状态中创建该对象怎么办?突然它不是一个反应对象,改变属性也不起作用。相反,您需要更新用于生成对象的其他一些基础属性。如果所有更新逻辑都在所有者中,这会更容易。
还有其他一些特定于商店的好处。
虽然 store 不直接参与响应性,但它确实有一个 subscribe 方法,插件可以使用该方法来跟踪调用突变的时间:
https://vuex.vuejs.org/api/#subscribe
如果您不经历突变,任何使用这些事件的插件都不会收到通知。例如,如果您使用插件将状态持久化到localStorage,那么突变之外的数据更改将不会持久化,至少不会立即持久化。如果页面刷新,则从localStorage 加载的状态将过期。
同样,Vue DevTools 支持称为时间旅行调试的东西。这只有在您使用突变时才能正常工作。
如果你还不熟悉,我建议你看看严格模式:
https://vuex.vuejs.org/guide/strict.html
最后我要指出商店经常被滥用,我个人认为 Vuex 商店的设计必须为此承担一些责任。我相信我上面概述的内容接近“官方”路线,但在我看来,这无异于描述使用巧克力防火板的最佳实践。