之前看vuex 的 3.x 版本源码,现在看下4.x版本源码有哪些不同?还是针对核心源码所以跟3.x版本,
【【源码】vuex@4.0.2】Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
- 官网示例代码
import { createApp } from 'vue'
import { createStore } from 'vuex'// 创建一个新的 store 实例
const store = createStore({
state () {
return {
count: 0
}
},
mutations: {
increment (state) {
state.count++
}
}
})const app = createApp({ /* 根组件 */ })// 将 store 实例作为插件安装
app.use(store)
createStore
export function createStore (options) {
return new Store(options)
}
createStore
函数很简单,直接返回一个Sotre
示例。Sotre 类
app.use
会调用传入参数对象的install
函数,所以先来分析install
函数install函数
export const storeKey = 'store'
install (app, injectKey) {
// 设置sotre实例到应用范围中的所有组件
app.provide(injectKey || storeKey, this)
// 添加$store属性作为全局的property,相当于Vue.prototype.$store
app.config.globalProperties.$store = this
// 忽略
const useDevtools = this._devtools !== undefined
? this._devtools
: __DEV__ || __VUE_PROD_DEVTOOLS__if (useDevtools) {
addDevtools(app, this)
}
}
install
函数首先使用Vue的依赖注入provide
来挂载sotre
实例,为什么要这么做?因为在setup
方法中无法访问this
。构造函数
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.`)
}
1.当前环境不支持Promise,报错:vuex 需要 Promise polyfill。
2.Store 函数必须使用 new 操作符调用。
const {
plugins = [],
strict = false,
devtools
} = options
从定义的
options
取出plugins
,strict
和devtools
.// store internal state
this._committing = false
// 用来存放处理后的用户自定义的actoins
this._actions = Object.create(null)
// 用来存放 actions 订阅
this._actionSubscribers = []
// 用来存放处理后的用户自定义的mutations
this._mutations = Object.create(null)
// 用来存放处理后的用户自定义的 getters
this._wrappedGetters = Object.create(null)
// 模块收集器,构造模块树形结构
this._modules = new ModuleCollection(options)
// 用于存储模块命名空间的关系
this._modulesNamespaceMap = Object.create(null)
// 订阅
this._subscribers = []
// 用来存放生成的本地 getters 的缓存
this._makeLocalGettersCache = Object.create(null)
this._devtools = devtools
这一块跟
vuex@3.x
几乎一模一样。就删除了_watcherVM
// bind commit and dispatch to self
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)
}
dispatch
和commit
函数绑定this
为store
实例。// 严格模式,默认是false
this.strict = strict
// 根模块的state
const state = this._modules.root.state// init root module.
// this also recursively registers all sub-modules
// and collects all module getters inside this._wrappedGetters
installModule(this, state, [], this._modules.root)// initialize the store state, which is responsible for the reactivity
// (also registers _wrappedGetters as computed properties)
resetStoreState(this, state)// apply plugins
// 插件:把实例对象 store 传给插件函数,执行所有插件。
plugins.forEach(plugin => plugin(this))
installModule
函数,初始化根模块,并且递归遍历所有子模块,并且收集所有模块的gettter
放置在_wrappedGetters
中。resetStoreState
函数, 初始化 store.state 响应式,并且注册
_wrappedGetters 作为 它的
computed`的属性。installModule
这里跟
vuex@3.x
版本逻辑几乎一模一样,忽略。resetStoreState(重要)