上篇写到 Store 构造函数中的 installModule 与 resetStoreVM 方法,这篇继续。
installModule
installModule 会处理开启 namespaced 的情况。
所有模块的 action、mutation、getter 都会被分别挂载到 Store._actions、Store._mutations、Store._wrappedGetters 上
如果没有开启 namespaced
,以 getter 为例会被处理成这样:1
2
3
4
5// Store._wrappedGetters
{
'getterName1': function wrappedGetter() { // code... },
'getterName2': function wrappedGetter() { // code... }
}
如果开启了 namespaced
,会被处理成这样:1
2
3
4
5// Store._wrappedGetters
{
'moduleName/getterName1': function wrappedGetter() { // code... },
'moduleName/getterName2': function wrappedGetter() { // code... }
}
1 | function installModule (store, rootState, path, module, hot) { |
resetStoreVM
1 | function resetStoreVM (store, state, hot) { |
先遍历所有定义了的 getter ,然后使用 Object.defineProperty 将 getter 的值都转到了 store._vm 上,等于说访问 store.getter.xxx 等同于访问 store._vm.xxx。1
2
3
4Object.defineProperty(store.getters, key, {
get: () => store._vm[key],
enumerable: true // for local getters
})
之后以 root.state 为 data 实例化一个 Vue 实例,以 Vue 的响应式能力来实现 Vuex 的功能。1
2
3
4
5
6
7// 设置 store._vm 为 Vue 实例
store._vm = new Vue({
data: {
$$state: state // state 为 root.state
},
computed
})
Vuex 设置了 store.state 的 get 函数,当使用 store.state.xxx 时实际返回的是 store._vm._data.$$state 中的数据。1
2
3
4
5
6
7
8
9
10
11
12// 获取 store.vm 的数据
get state () {
return this._vm._data.$$state
}
// 设置 state(不允许直接修改 state)
set state (v) {
if (process.env.NODE_ENV !== 'production') {
// 只可使用 store.replaceState() 替换存储状态,不允许直接设置
assert(false, `use store.replaceState() to explicit replace store state.`)
}
}
接下来看其他部分:
Store.commit 方法
1 | // 提交 mutation https://vuex.vuejs.org/zh/api/#commit (注意:mutation为同步事物) |
mutation 执行后,会执行所有订阅了该 mutation 的回调,订阅相关 API: https://vuex.vuejs.org/zh/api/#subscribe
Store.dispatch 方法
1 | // 分发 action https://vuex.vuejs.org/zh/api/#dispatch(action 内可异步) |
action 的执行同样也有订阅回调,与 mutation 不同的是 action 的订阅有两个 一个 before,一个 after 分别在 执行前、执行后调用。