文档here
你不能直接改变store 的状态.改变store 状态的唯一方法是committing mutations.
我的问题是,这是一种良好的做法,还是Vuex状态的内部运作方式?换句话说,Vuex状态是否与Vue数据的react 方式相同(它将JS对象转换为可观察对象),还是其他什么?
一个类似的问题——你能直接改变动作中的状态,而不是制造Mutations 吗?我知道这是一种不好的做法,它失go 了遵循惯例所提供的一些可追溯性——但它有效吗?
文档here
你不能直接改变store 的状态.改变store 状态的唯一方法是committing mutations.
我的问题是,这是一种良好的做法,还是Vuex状态的内部运作方式?换句话说,Vuex状态是否与Vue数据的react 方式相同(它将JS对象转换为可观察对象),还是其他什么?
一个类似的问题——你能直接改变动作中的状态,而不是制造Mutations 吗?我知道这是一种不好的做法,它失go 了遵循惯例所提供的一些可追溯性——但它有效吗?
你能直接改变动作中的状态而不是制造Mutations 吗?我知道这是一种不好的做法,它失go 了遵循惯例所提供的一些可追溯性——但它有效吗?
工作正常,但会抛出警告和错误.
vue.js:584 [Vue warn]: Error in callback for watcher "function () { return this._data.$$state }": "Error: [vuex] Do not mutate vuex store state outside mutation handlers."
(found in <Component>)
warn @ vue.js:584
...
vue.js:1719 Error: [vuex] Do not mutate vuex store state outside mutation handlers.
at assert (VM260 vuex.js:103)
谁知道这之后还会有什么东西坏掉.
请自行查看(注意模板中的数据更新):
const store = new Vuex.Store({
strict: true,
state: {
people: []
},
mutations: {
populate: function (state, data) {
//Vue.set(state, 'people', data);
}
}
});
new Vue({
store,
el: '#app',
mounted: function() {
let self = this;
this.$http.get('https://api.myjson.com/bins/g07qh').then(function (response) {
// setting without commit
Vue.set(self.$store.state, 'people', response.data);
//self.$store.commit('populate', response.data)
}).catch(function (error) {
console.dir(error);
});
},
computed: {
datadata: function() {
return this.$store.state.people
}
},
})
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/vuex"></script>
<script src="https://unpkg.com/vue-resource"></script>
<div id="app">
Data: {{ datadata }}
</div>
Vuex状态的react 方式与Vue数据的react 方式相同(它将js对象转换为可观察对象),还是其他什么?
对事实上,正是Vue本身使store 对象具有react 性.从Mutations official docs人中:
Mutations 遵循Vue的react 性规则
由于Vue使Vuexstore 的状态变为react 状态,所以当我们改变
更喜欢用所有需要的字段预先初始化store 的初始状态.
向对象添加新属性时,应:
使用
Vue.set(obj, 'newProp', 123)
,或用一个新的替换那个物体.例如,使用stage-3 object spread syntax我们可以
state.obj = { ...state.obj, newProp: 123 }
因此,即使在代码中,如果覆盖可观察对象或直接创建新属性(不调用Vue.set(obj, 'newProp', newValue)
),对象也不会是被动的.
因此,可观察对象似乎与常规Vue数据略有不同——变化只允许在变异处理程序中发生.是这样吗?
他们可能是,但我不相信他们是.文件和证据(见下文vm.$watch
条讨论)指出,它们与data
个物体完全相同,至少在react /可观察行为方面是如此.
对象如何"知道"它是从不同的上下文中变异的?
这是个好问题.请允许我重新措辞:
如果从Vue内部调用
Vue.set(object, 'prop', data);
会引发异常(请参见上面的演示),为什么从变异函数内部调用Vue.set(object, 'prop', data);
不会引发异常?
答案是within Store.commit()
's code.它执行变异代码through a _withCommit()
internal function.
this _withCommit()
does is it sets a flag this._committing
to true
和then执行Mutations 代码(执行后返回_committing
到false
).
Vuex存储是watching the states' variables,如果它注意到(又名观察者触发)variable changed while the _committing
flag was false
it throws the warning.
(额外奖励:do notice that vuex uses vm.$watch
——如果不熟悉,请参阅Vue's vm.$watch
API docs——观察变量,这是另一个提示,说明状态对象与数据对象相同——它们依赖于Vue的内部 struct .)
现在,为了证明我的观点,让我们自己打"trick" vuex by setting 100 to 101,然后从变异子外面打Vue.set()
.如下图所示,no warning被触发.touch .
const store = new Vuex.Store({
strict: true,
state: {
people: []
},
mutations: {
populate: function (state, data) {
//Vue.set(state, 'people', data);
}
}
});
new Vue({
store,
el: '#app',
mounted: function() {
let self = this;
this.$http.get('https://api.myjson.com/bins/g07qh').then(function (response) {
// trick the store to think we're using commit()
self.$store._committing = true;
// setting without commit
Vue.set(self.$store.state, 'people', response.data);
// no warning! yay!
}).catch(function (error) {
console.dir(error);
});
},
computed: {
datadata: function() {
return this.$store.state.people
}
},
})
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/vuex"></script>
<script src="https://unpkg.com/vue-resource"></script>
<div id="app">
Data: {{ datadata }}
</div>