1. 为什么Vuex要通过mutations修改state,而不能直接修改
因为state是实时更新的,mutations无法进行异步操作,而如果直接修改state的话是能够异步操作的,当你异步对state进行操作时,还没执行完,这时候如果state已经在其他地方被修改了,这样就会导致程序存在问题了。所以state要同步操作,通过mutations的方式限制了不允许异步。
vuex 不但是一种全局修改数据的工具,更重要的意义是在于把跨组件的交互,拆分为基于状态管理的处理。
使用如 vuex 本身就是希望基于这样一个数据结构的约定,使得项目代码更加直观和简单。每一个 state树对应整个项目的一个数据,每一个 mutation 执行完成后都可以更新到一个新的状态。这样 devtools 就可以打个 snapshot 存下来。可以尝试开着 devtool 调用一个异步的 action,可以清楚地看到它所调用的 mutation 是何时被记录下来的,并且可以立刻查看 mutation 对应的状态。
所以,通过commit 提交 mutation 的方式来修改 state 时,vue的调试工具能够记录每一次 state 的变化,这样方便调试。但是如果是直接修改state,则没有这个记录,那样做会使状态不受我们管控。如果是多个模块需要引用一个state的,然后每个人可能由不同的人开发,如果直接修改值,可能会造成数据的混乱,Mutation 也记录不到,到时候调试会有麻烦。但是通过 mutation 修改 state 这样设计,就有个统一的地方进行逻辑运算去修改。如果逻辑有变动,修改一个地方就可以了。
vuex 更改state 是 dispatch 给 action,action 再 commit 给 mutation,这样实现了单向数据改动 区别普通双向绑定
2. vuex为什么不直接修改数据?
通过commit 提交 mutation 的方式来修改 state 时,vue的调试工具能够记录每一次 state 的变化,这样方便调试。但是如果是直接修改state,则没有这个记录,那样做会使状态不受我们管控。如果是多个模块需要引用一个state的,然后每个人可能由不同的人开发,如果直接修改值,可能会造成数据的混乱,Mutation 也记录不到,到时候调试会有麻烦。但是通过 mutation 修改 state 这样设计,就有个统一的地方进行逻辑运算去修改。如果逻辑有变动,修改一个地方就可以了。
3. vuex中为什么把异步操作封装在action,把同步操作放在mutations?
知乎问题: 官方文档说明:“在 mutation 中混合异步调用会导致你的程序很难调试。例如,当你能调用了两个包含异步回调的 mutation 来改变状态,你怎么知道什么时候回调和哪个先回调呢?这就是为什么我们要区分这两个概念。在 Vuex 中,我们将全部的改变都用同步方式实现。我们将全部的异步操作都放在Actions中。”
但我不明白的是,我如果同时出发了两个异步的actions,那么这两个回调的时间不一样,那么对于state的更新还是存在竞态的。所以我觉得这样进行区分并不能解决“那么先回调,哪个后回调”来更新state的问题。
4. v-model和vuex有冲突么?
当在严格模式中使用 Vuex 时,在属于 Vuex 的 state 上使用 v-model
会比较棘手:
<input v-model="obj.message">
假设这里的 obj
是在计算属性中返回的一个属于 Vuex store 的对象,在用户输入时,v-model
会试图直接修改 obj.message
。在严格模式中,由于这个修改不是在 mutation 函数中执行的, 这里会抛出一个错误。
用“Vuex 的思维”去解决这个问题的方法是:给 <input>
中绑定 value,然后侦听 input
或者 change
事件,在事件回调中调用一个方法:
<input :value="message" @input="updateMessage">
// ...
computed: {
...mapState({
message: state => state.obj.message
})
},
methods: {
updateMessage (e) {
this.$store.commit('updateMessage', e.target.value)
}
}
下面是 mutation 函数:
// ...
mutations: {
updateMessage (state, message) {
state.obj.message = message
}
}