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