乐趣区

关于vuex:源码vuex402

之前看 vuex 的 3.x 版本源码,当初看下 4.x 版本源码有哪些不同?还是针对外围源码

Vuex 是一个专为 Vue.js 利用程序开发的 状态管理模式 + 库。它采纳集中式存储管理利用的所有组件的状态,并以相应的规定保障状态以一种可预测的形式发生变化。

所以跟 3.x 版本,

  • 官网示例代码
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,strictdevtools.

// 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)
}

dispatchcommit 函数绑定 thisstore实例。

// 严格模式,默认是 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(重要)

退出移动版