在上一篇笔记中:Vuex 4源码学习笔记 - Vuex是怎么与Vue结合?(三)
我们复习了Vuex的使用方式,以及为什么要使用Vuex,同时看到了Vuex是如何与Vue去结合到一起的。
Vuex是通过Vue插件的方式,通过use函数将Vuex实例对象绑定到Vue中。
然后我们在页面或者组件中可以通过useStore 函数或者this.$store 两种方式在页面中访问到store实例。
首先创建Vuex实例的方式为调用createStore函数来调用
import { createStore } from 'vuex'
export default createStore({
state: { },
getters: { },
actions: { },
mutations: { }
})
createStore函数的源代码,可以看到实际是new了一个Store类的对象
export function createStore (options) {
return new Store(options)
}
Store 构造函数
然后我们看到Store类的源代码,new的第一步首先就是调用constructor构造函数
export class Store {
constructor (options = {}) {
if (__DEV__) {
assert(typeof Promise !== 'undefined', `vuex requires a Promise polyfill in this browser.`)
assert(this instanceof Store, `store must be called with the new operator.`)
}
const {
plugins = [],
strict = false,
devtools
} = options
this._committing = false
this._actions = Object.create(null)
this._actionSubscribers = []
this._mutations = Object.create(null)
this._wrappedGetters = Object.create(null)
this._modules = new ModuleCollection(options)
this._modulesNamespaceMap = Object.create(null)
this._subscribers = []
this._makeLocalGettersCache = Object.create(null)
this._scope = null
this._devtools = devtools
const store = this
const { dispatch, commit } = this
this.dispatch = function boundDispatch (type, payload) {
return dispatch.call(store, type, payload)
}
this.commit = function boundCommit (type, payload, options) {
return commit.call(store, type, payload, options)
}
this.strict = strict
const state = this._modules.root.state
installModule(this, state, [], this._modules.root)
resetStoreState(this, state)
plugins.forEach(plugin => plugin(this))
}
}
可以看到Store的构造函数除了初始化一些内部变量以外,主要做了两件事情,一是执行了installModule(初始化module),二是通过resetStoreState(通过Vue3的reactive使store的状态实现“响应式”)。
installModule
installModule的作用主要是为module加上namespace名字空间(如果有)后,注册mutation、action以及getter,同时递归安装所有子module。
export function installModule (store, rootState, path, module, hot) {
const isRoot = !path.length
const namespace = store._modules.getNamespace(path)
if (module.namespaced) {
if (store._modulesNamespaceMap[namespace] && __DEV__) {
console.error(`[vuex] duplicate namespace ${namespace} for the namespaced module ${path.join('/')}`)
}
store._modulesNamespaceMap[namespace] = module
}
if (!isRoot && !hot) {
const parentState = getNestedState(rootState, path.slice(0, -1))
const moduleName = path[path.length - 1]
store._withCommit(() => {
if (__DEV__) {
if (moduleName in parentState) {
console.warn(
`[vuex] state field "${moduleName}" was overridden by a module with the same name at "${path.join('.')}"`
)
}
}
parentState[moduleName] = module.state
})
}
const local = module.context = makeLocalContext(store, namespace, path)
module.forEachMutation((mutation, key) => {
const namespacedType = namespace + key
registerMutation(store, namespacedType, mutation, local)
})
module.forEachAction((action, key) => {
const type = action.root ? key : namespace + key
const handler = action.handler || action
registerAction(store, type, handler, local)
})
module.forEachGetter((getter, key) => {
const namespacedType = namespace + key
registerGetter(store, namespacedType, getter, local)
})
module.forEachChild((child, key) => {
installModule(store, rootState, path.concat(key), child, hot)
})
}
resetStoreState
执行完成各module的install后,执行resetStoreState方法,进行store组件的初始化。
resetStoreState(this, state)
我们可以把Vuex理解为Vue的组件,所有配置的state、actions、mutations以及getters都是其组件的属性,所有操作都是围绕着这个组件。下面我们来看其细节:
export function resetStoreState (store, state, hot) {
const oldState = store._state
const oldScope = store._scope
store.getters = {}
store._makeLocalGettersCache = Object.create(null)
const wrappedGetters = store._wrappedGetters
const computedObj = {}
const computedCache = {}
const scope = effectScope(true)
scope.run(() => {
forEachValue(wrappedGetters, (fn, key) => {
computedObj[key] = partial(fn, store)
computedCache[key] = computed(() => computedObj[key]())
Object.defineProperty(store.getters, key, {
get: () => computedCache[key].value,
enumerable: true
})
})
})
store._state = reactive({
data: state
})
store._scope = scope
if (store.strict) {
enableStrictMode(store)
}
if (oldState) {
if (hot) {
store._withCommit(() => {
oldState.data = null
})
}
}
if (oldScope) {
oldScope.stop()
}
}
今天我们看了Store的构造函数,和构造函数中的installModule和resetStoreState函数的作用。
installModule函数主要用来处理初始化module,和所有子module的注册。
resetStoreState函数主要用俩处理store的state和getter的响应式初始化。
明天我们接着分析其中的一些函数细节,和组件中的获取state和action函数连起来看。
一起学习更多前端知识,微信搜索【小帅的编程笔记】,每天更新
|