zoukankan      html  css  js  c++  java
  • VueX源码分析(4)

    VueX源码分析(4)

    • /module
    • store.js

    /module/module.js

    import { forEachValue } from '../util'
    
    // Base data struct for store's module, package with some attribute and method
    export default class Module {
      constructor (rawModule, runtime) {
        this.runtime = runtime
        // Store some children item
        this._children = Object.create(null)
        // Store the origin module object which passed by programmer
        this._rawModule = rawModule
        const rawState = rawModule.state
    
        // Store the origin module's state
        this.state = (typeof rawState === 'function' ? rawState() : rawState) || {}
      }
    
      get namespaced () {
        return !!this._rawModule.namespaced
      }
    
      addChild (key, module) {
        this._children[key] = module
      }
    
      removeChild (key) {
        delete this._children[key]
      }
    
      getChild (key) {
        return this._children[key]
      }
    
      update (rawModule) {
        this._rawModule.namespaced = 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
        }
      }
    
      forEachChild (fn) {
        forEachValue(this._children, fn)
      }
    
      forEachGetter (fn) {
        if (this._rawModule.getters) {
          forEachValue(this._rawModule.getters, fn)
        }
      }
    
      forEachAction (fn) {
        if (this._rawModule.actions) {
          forEachValue(this._rawModule.actions, fn)
        }
      }
    
      forEachMutation (fn) {
        if (this._rawModule.mutations) {
          forEachValue(this._rawModule.mutations, fn)
        }
      }
    }
    
    

    解析:

    • Module是store模块的类,基本模块的静态属性和一些方法
    • rawModule就是我们定义的模块对象{ namespaced, state, actions, mutations, getters }
    • this.state = (typeof rawState === 'function' ? rawState() : rawState) || {}定义状态可以用函数的方式定义的,这里要先判断状态是不是函数,是函数要执行函数后的值。
    • _children记录嵌套模块的模块{ state, modules: { modules: {} } }
    • namespaced就是是否使用命名空间
    • addChild、removeChild、getChild是嵌套模块的一些操作方法
    • 还有一些遍历的方法但是只有children、getters、actions、mutations的遍历,没有this.state,那个update模块也是,不会更新state
    • 更新只更新namespaced、actions、mutations、getters

    /module/module-collection.js

    主要类ModuleCollection,还有一些辅助函数,先分析辅助函数再分析主要类。
    主要将所有模块合并的类。

    断言函数(只在开发者环境起作用)

    const functionAssert = {
      assert: value => typeof value === 'function',
      expected: 'function'
    }
    
    const objectAssert = {
      assert: value => typeof value === 'function' ||
        (typeof value === 'object' && typeof value.handler === 'function'),
      expected: 'function or object with "handler" function'
    }
    
    const assertTypes = {
      getters: functionAssert,
      mutations: functionAssert,
      actions: objectAssert
    }
    
    function assertRawModule (path, rawModule) {
      Object.keys(assertTypes).forEach(key => {
        if (!rawModule[key]) return
    
        const assertOptions = assertTypes[key]
    
        forEachValue(rawModule[key], (value, type) => {
          assert(
            assertOptions.assert(value),
            makeAssertionMessage(path, key, type, value, assertOptions.expected)
          )
        })
      })
    }
    
    function makeAssertionMessage (path, key, type, value, expected) {
      let buf = `${key} should be ${expected} but "${key}.${type}"`
      if (path.length > 0) {
        buf += ` in module "${path.join('.')}"`
      }
      buf += ` is ${JSON.stringify(value)}.`
      return buf
    }
    

    解析:

    • path是嵌套模块的名称。如根模块为[],嵌套模块shop/card['shop', 'card']。主要功能是模块的寻址路径,可以根据这个路径获取该模块。
    • makeAssertionMessage(path, key, type, value, expected)中的key就是我们自定义模块的字段:如state、mutations等,这个断言就是判断我们定义的字段命是否符合要求。

    ModuleCollection

    export default class ModuleCollection {
      constructor (rawRootModule) {
        // register root module (Vuex.Store options)
        this.register([], rawRootModule, false)
      }
    
      get (path) {
        return path.reduce((module, key) => {
          return module.getChild(key)
        }, this.root)
      }
    
      getNamespace (path) {
        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 (process.env.NODE_ENV !== 'production') {
          assertRawModule(path, rawModule)
        }
    
        const newModule = new Module(rawModule, runtime)
        if (path.length === 0) {
          this.root = newModule
        } else {
          const parent = this.get(path.slice(0, -1))
          parent.addChild(path[path.length - 1], newModule)
        }
    
        // register nested modules
        if (rawModule.modules) {
          forEachValue(rawModule.modules, (rawChildModule, key) => {
            this.register(path.concat(key), rawChildModule, runtime)
          })
        }
      }
    
      unregister (path) {
        const parent = this.get(path.slice(0, -1))
        const key = path[path.length - 1]
        if (!parent.getChild(key).runtime) return
    
        parent.removeChild(key)
      }
    }
    
    function update (path, targetModule, newModule) {
      if (process.env.NODE_ENV !== 'production') {
        assertRawModule(path, newModule)
      }
    
      // update target module
      targetModule.update(newModule)
    
      // update nested modules
      if (newModule.modules) {
        for (const key in newModule.modules) {
          if (!targetModule.getChild(key)) {
            if (process.env.NODE_ENV !== 'production') {
              console.warn(
                `[vuex] trying to add a new module '${key}' on hot reloading, ` +
                'manual reload is needed'
              )
            }
            return
          }
          update(
            path.concat(key),
            targetModule.getChild(key),
            newModule.modules[key]
          )
        }
      }
    }
    

    解析:

    • 主要功能是将所有模块合并起来,以及注册和注销所有模块。
    • register就是将我们自己定义的对象模块new Module(自己定义的对象模块),这个注册可以递归地注册所有模块,包括嵌套的
    • unregistermodule.js文件中的delete this._children[key]是直接调用delete删除
    • this.root就是最外层的modules
  • 相关阅读:
    jetty运行服务
    对象的属性值是数组,如何使用ko跨页面绑定?
    Maven打包时出现“Show Console View”错误弹出框,错误详情为“An internal error has occurred. java.lang.NullPointerException”的解决方法
    记录一次CDH集群邮件报警功能的设置
    jupyter notebook
    MacOS开发环境搭建
    Manico--自定义应用快速切换
    Synergy--跨平台的键鼠共享工具
    Sublime Text3 个人使用安装设置
    Typora--我用过的最好用的markdown编辑器
  • 原文地址:https://www.cnblogs.com/lantuoxie/p/9353786.html
Copyright © 2011-2022 走看看