美文网首页让前端飞
前端日报--installModule(三)

前端日报--installModule(三)

作者: 拿着号码牌徘徊 | 来源:发表于2019-03-26 22:52 被阅读3次

vuex中的初始化模块installModule就是初始化三个东西Mutation,Action,Getter

***installModule 函数可接收5个参数,store、rootState、path、module、hot,store 表示当前 Store 实例,rootState 表示根 state,path 表示当前嵌套模块的路径数组,module 表示当前安装的模块,hot 当动态改变 modules 或者热更新的时候为 true。***
installModule(this, state, [], this._modules.root)
function installModule (store, rootState, path, module, hot) {
  const isRoot = !path.length
  const namespace = store._modules.getNamespace(path)

  // register in namespace map
  if (module.namespaced) {
    store._modulesNamespaceMap[namespace] = module
  }

  // set state
如果不是热更新并且不是热更新,那么当前状态就会挂载在当前模块命名的对象里。
  if (!isRoot && !hot) {
    const parentState = getNestedState(rootState, path.slice(0, -1))
    const moduleName = path[path.length - 1]
    store._withCommit(() => {
      Vue.set(parentState, moduleName, module.state)
    })
  }

  const local = module.context = makeLocalContext(store, namespace, path)

  module.forEachMutation((mutation, key) => {
    const namespacedType = namespace + key
    registerMutation(store, namespacedType, mutation, local)
  })

  module.forEachAction((action, key) => {
    const type = action.root ? key : namespace + key
    const handler = action.handler || action
    registerAction(store, type, handler, local)
  })

  module.forEachGetter((getter, key) => {
    const namespacedType = namespace + key
    registerGetter(store, namespacedType, getter, local)
  })

  module.forEachChild((child, key) => {
     根据path数组来继续注册模块
    installModule(store, rootState, path.concat(key), child, hot)
  })
}

接下来我们看看registerMutation,registerAction的代码,两者都通过entry来存放所对应的每个mutaion和Action,这样可以通过type路径找到对应的mutation和action。registerGetter稍有不同,它不能重复type,这和它挂载在compute有关。

function registerMutation (store, type, handler, path = []) {
  const entry = store._mutations[type] || (store._mutations[type] = [])
  entry.push(function wrappedMutationHandler (payload) {
    handler(getNestedState(store.state, path), payload)
  })
}
function registerAction (store, type, handler, path = []) {
const entry = store._actions[type] || (store._actions[type] = [])
  const { dispatch, commit } = store
  entry.push(function wrappedActionHandler (payload, cb) {
    let res = handler({
      dispatch,
      commit,
      getters: store.getters,
      state: getNestedState(store.state, path),
      rootState: store.state
    }, payload, cb)
    if (!isPromise(res)) {
      res = Promise.resolve(res)
    }
    if (store._devtoolHook) {
      return res.catch(err => {
        store._devtoolHook.emit('vuex:error', err)
        throw err
      })
    } else {
      return res
    }
  })
 }
function registerGetter (store, type, rawGetter, local) {
  if (store._wrappedGetters[type]) {
    if (process.env.NODE_ENV !== 'production') {
      console.error(`[vuex] duplicate getter key: ${type}`)
    }
    return
  }
  store._wrappedGetters[type] = function wrappedGetter (store) {
    return rawGetter(
      local.state, // local state
      local.getters, // local getters
      store.state, // root state
      store.getters // root getters
    )
  }
}

重头戏是vuex是如何实现响应式的

function resetStoreVM (store, state, hot) {
  const oldVm = store._vm

  // bind store public getters
  store.getters = {}
  const wrappedGetters = store._wrappedGetters
  const computed = {}
在这里循环遍历store._wrappedGetters所有的getter,并且通过partial方法返回一个匿名函数,这个匿名函数式是getter具体的方法。同时呢,把getters挂载在store._vm上,而store._vm是实例化的Vue.至此呢,vuex的数据和vue其他数据一样实现了响应式。
  forEachValue(wrappedGetters, (fn, key) => {
    // use computed to leverage its lazy-caching mechanism
    // direct inline function use will lead to closure preserving oldVm.
    // using partial to return function with only arguments preserved in closure enviroment.
    computed[key] = partial(fn, store)
    Object.defineProperty(store.getters, key, {
      get: () => store._vm[key],
      enumerable: true // for local getters
    })
  })

  // use a Vue instance to store the state tree
  // suppress warnings just in case the user has added
  // some funky global mixins
  const silent = Vue.config.silent
  Vue.config.silent = true
  store._vm = new Vue({
    data: {
      $$state: state
    },
    computed
  })
  Vue.config.silent = silent

  // enable strict mode for new vm
  if (store.strict) {
    enableStrictMode(store)
  }

  if (oldVm) {
    if (hot) {
      // dispatch changes in all subscribed watchers
      // to force getter re-evaluation for hot reloading.
      store._withCommit(() => {
        oldVm._data.$$state = null
      })
    }
    Vue.nextTick(() => oldVm.$destroy())
  }
}

相关文章

  • 前端日报--installModule(三)

    vuex中的初始化模块installModule就是初始化三个东西Mutation,Action,Getter 接...

  • vue插件

    vuex 函数过程new Store() -> (resetStoreVM)installModule -> (g...

  • 20161205 码农日报

    20161205 码农日报 前端日报栏目数据来自码农头条(我开发的爬虫),每日分享前端、移动开发、设计、资源和资讯...

  • 20170116 码农日报

    20170116 码农日报 前端日报栏目数据来自码农头条(我开发的爬虫),每日分享前端、移动开发、设计、资源和资讯...

  • Android开发那些事

    【掘金日报】第三期 老夫这里有一本“深度学习”的秘籍,要不要? 掘金日报主打分享优质深度技术内容,技术内容分:前端...

  • 20161206前端日报

    前端日报栏目数据来自码农头条(我开发的爬虫),每日分享前端、移动开发、设计、资源和资讯等,为开发者提供动力,点击S...

  • 20160903 码农头条日报

    前端日报栏目数据来自码农头条(前端机器人),每日分享前端、移动开发、设计、资源和资讯等,为开发者提供动力,如果觉得...

  • vuex源码分析(四)——installModule

    本文参考珠峰架构公开课之vuex实现原理 之前的文章谈到了module的数据的注册,接下来就是基于注册数据,执行i...

  • 20170822 前端开发日报

    几种 JavaScript 动画库推荐 JavaScript 库对设计师和开发人员来说,都是非常有用的工具。它们可...

  • 20170815 前端开发日报

    JavaScript闭包,只学这篇就够了 闭包不是魔法 这篇文章使用一些简单的代码例子来解释JavaScript闭...

网友评论

    本文标题:前端日报--installModule(三)

    本文链接:https://www.haomeiwen.com/subject/nmchpqtx.html