vuex 使用方法
import Vuex from 'vuex'
import Vue from 'vue'
Vue.use(Vuex)
export default new Vuex.store({
state = {},
getters = {},
mutations = {},
actions = {}
})
复制代码
vue.use() 方法
vue.use()方法必须包含install方法,目的就是把插件挂载到vue上 vue-router, vuex都是同样的原理
install方法的实现
let Vue
let install = (_Vue) => {
Vue = _Vue
// 给所有的组建均挂载
Vue.mixin({
beforeCreate () {
if (this.$options && this.$options.store) {
this.$store = this.$options.store
} else {
this.$store = this.$parent && this.$parent.$store
}
}
})
}
复制代码
Store函数的实现
class Store {
constructor(options) {
const { state } = options
this.getters = Object.create(null)
this.actions = Object.create(null)
this.mutations = Object.create(null)
// module收集器
this.modules = new ModuleCollection(options)
this._vm = new Vue({
data: {
state
}
})
const { diapatch, commit } = this
this.dispatch = (type) => {
return dispatch.call(this, type)
}
this.commit = () => {
return commit.call(this, type)
}
// 初始化module,同时递归注册所有module
installModule(this, state, [], this.modules.root)
}
get state () {
return this._vm.state
}
dispatch (type) {
this.actions[type].forEach(fn => fn())
}
commit (type) {
this.mutations[type].forEach(fn => fn())
}
}
复制代码
收集所有module
ModuleCollection 主要将传入的 options 对象整个构造为一个 module 对象, 并循环调用 register 为其中的 modules 属性进行模块注册, 使其都成为 module 对象, 最后 options 对象被构造成一个完整的组件树.
class ModuleCollection {
constructor (options) {
this.register([], options)
}
register (path, rawModule) {
let newModule = {
_raw: rawModule,
_children: {},
state: rawModule.state
}
if (path.length === 0 ) {
this.root = newModule
} else {
let parent = path.slice(0, -1).reduce((root, current) => {
return root._children[current]
}, this.root)
parent._children[path[path.length - 1]] = newModule
}
if (rawModule.modules) {
forEach(rawModule.modules, (childName, module) => {
this.register(path.concat[childName], module)
})
}
}
}
复制代码
初始化installModule函数的实现
注册mutation、action以及getter,同时递归安装所有子module。
function installModule (store, rootState, path, rootModule) {
if (path.length > 0 ) {
let parent = path.slice(0, -1).reduce((root, current) => {
return root._children[current]
}, rootModule)
Vue.set(parent, path[path.length - 1], rootModule.state)
}
if (rootModule._raw.getters) {
forEach(rootModule._raw.getters, (getterName, getterFn) => {
Object.defineProperty(store.getters, getterName, {
get: () => {
return getterFn(rootModule.store)
}
})
})
}
if (rootModule._raw.actions) {
forEach(rootModule._raw.actions, (actionName, actionFn) => {
let entry = store.actions[actionName] || (store.actions[actionName] = [])
entry.push(() => {
actionFn.call(store, store)
})
})
}
if (rootModule._raw.mutations) {
forEach(rootModule._raw.mutations, (mutationsName, mutationsFn) => {
let entry = store.mutations[mutationsName] || (store.mutations[mutationsName] = [])
entry.push(() => {
mutationsFn.call(store, rootModule.store)
})
})
}
forEach(rootModule._children, (childName, module) => {
installModule(store, rootState, path.concat(childName), module)
})
}
复制代码
参考资料:
Vuex源码阅读分析