install
Vuex's dependency on Vue
if(! Vue &&typeof window! = ='undefined' && window.Vue){
install(window.Vue)
}
Copy the code
install
function install(_Vue){
// Determine whether Vue has been declared and whether there are duplicate uses
if(Vue && _Vue === Vue){
if(__DEV__){
console.error(`[vuex] already installed. Vue.use(Vuex) should be called only once`)}return
}
// Assign the Vue object
Vue = _Vue
applyMixin(Vue)
}
Copy the code
applyMixin
export default function(Vue){
// Get the imported vUE version
const version = Number(Vue.version.split('. ') [0])
// Determine the version and initialize vuex in the hook function
if(version >= 2){
Vue.mixin({beforeCreate:vuexInit})
}else{
/ / rewrite _init
const _init = Vue.prototype._init
Vue.prototype._init = function(options = {}){
options.init = options.init ? [vuexInit].concat(options.init) : vuexInit
_init.call(this,options)
}
}
}
// Vuex is initialized
function vuexInit(){
const options = this.$options
/ / inject $store
if(options.store){
this.$store = typeof options.store === 'function' ? options.store() : options.store
}else if(options.parent && options.parent.$store){
this.$store = options.parent.$store
}
}
Copy the code
modules
// Set the module
this._modules = new ModuleCollection(options)
Copy the code
ModuleCollection
class ModuleCollection{
constructor(rawRootModule){
// Register the root node module
this.register([],rawRootModule,false)}get(path){
// Find submodules from root node based on path
return path.reduce((module,key) = >{
return module.getChild(key)
},this.root)
}
getNamespace(path){
// Get the module name
let module = this.root
return path.reduce((namespace,key) = >{
module = module.getChild(key)
return namespace + (module.namespaced ? key + '/' : ' ')},' ')}update(rawRootModule){
update([],this.root,rawRootModule)
}
register(path,rawModule,runtime = true){
if(__DEV__){
// Getter /mutation/actionss for the validation module
assertRawModule(path,rawModule)
}
// Create a node
const newModule = new Module(rawModule,runtime)
if(path.length === 0) {// Initialize the root node
this.root = newModule
}else{
// Get the parent node
const parent = this.get(path.lice(0, -1))
// Add a module with the corresponding key value for the parent node
parent.addChild(path[path.length - 1],newModule)
}
if(rawModule.modules){
// Traverses the root node submodule registration
forEachValue(rawModule.modules,(rawChildModule,key) = > {
// Register submodules
this.register(path.concat[key],rawChildModule,runtime)
})
}
}
unregister(path){
// Get the parent node
const parent = this.get(path.slice(0, -1))
const key = path[path.length - 1]
// Get the child node to delete
const child = parent.getChild(key)
if(! child){if(__DEV__){
console.warn(`[vuex] tring to unregister module '${key}', which is not registerd`)}return
}
// Non-runtime
if(! child.runtime){return
}
// Delete submodules
parent.removeChild(key)
}
isRegistered(path){
// Get the parent node
const parent = this.get(path.slice(0, -1))
const key = path[path.length - 1]
// Check whether the child node exists
if(parent){
return parent.hasChild(key)
}
return false}}Copy the code
assertRawModule
const functionAssert = {
assert: value= > typeof value === 'function'.// Annotate the getter/mutations type
expected:'function'
}
const objectAssert = {
assert:value= > typeof value === 'function'| | -typeof value === 'object' && typeof value.handler === 'function'),
expected:'function or object with "handler" function'
}
// Annotate the function type in modules
const assertTypes = {
getters:functionAssert,
mutations:functionAssert,
actions:objectAssert
}
function assertRawModule(path,rawModule){
Object.keys(assertTypes).forEach(key= > {
// decide that the module lacks getter/actions/mutations
if(! rawModule[key])return
const assertOptions = assertTypes[key]
// the traversal method
forEachValue(rawModule[key],(value,type) = > {
// Check whether the method type matches
assert(assertOptions.assert(value),makeAssertionMessage(path,key,type,value,assertOptions.expected))
})
})
}
// Output the method field according to the module name
function makeAssertionMessage(path,key,type,value,assertOptions.expected){
let buf = `${key} should be ${expected} but "${key}.${type}"`
if(path.length > 0){
buf += `in module "${path.join('. ')}"`
}
buf += ` is The ${JSON.stringify(value)}`
return buf
}
Copy the code
update
function update(path,targetModule,newMoudle){
// Validates newModule's field methods
if(__DEV__){
assertRawMoudle(path,newModule)
}
// Update the root node
targetMoudle.update(newModule)
if(newModule.modules){
for(const key in newModule.modules){
if(! targetModule.getChild(key)){if(__DEV__){
console.warn(`[vuex] trying to add a new module '${key}' on hot reloading, manual reload is needed`)}return
}
// Update submodules
update(path.concat(key),targetModule.getChild(key),newModule.modules[key])
}
}
}
Copy the code
Module
class Module{
constructor(rawModule,runtime){
// Get the runtime
this.runtime = runtime
/ / modules
this._children = Object.create(null)
this._rawModule = rawModule
// Get the state of the module
const rawState = rawModule.state
this.state = (typeof rawState === 'function' ? rawState() : rawState) || {}
}
get namespaced() {return!!!!!this._rawModule.namespaced
}
// Add child nodes to the module
addChild(key,module){
this._children[key] = module
}
// Remove the child node
removeChild(key){
delete this._children[key]
}
// Get the child node
getChild(key){
return this._children[key]
}
// Check whether child nodes are included
hasChild(key){
return key in this._children
}
update(rawModule){
// Update current module
this._rawModule.namspaced = rawModule.namespaced
if(rawModule.actions){
this._rawModule.actions = rawModule.actions
}
if(rawModule.mutations){
this._rawModule.mutations = rawModule.mutations
}
if(rawModule.getters){
this._rawModule.getters = rawModule.getters
}
}
// Iterate over the submodule, execute fn
forEachChild(fn){
forEachValue(this._children,fn)
}
/ / traverse getters
forEachGetter(fn){
if(this._rawModule.getters){
forEachValue(this._rawModule.getters,fn)
}
}
/ / traverse the actions
forEachAction(fn){
if(this._rawModule.actions){
forEachValue(this._rawModule.actions,fn)
}
}
/ / traverse mutations
forEachMutation(fn){
if(this._rawModule.mutations){
forEachValue(this._rawMoudle.mutations,fn)
}
}
}
Copy the code