详解vuex之store源码简单解析


Posted in Javascript onJune 13, 2019

关于vuex的基础部分学习于https://3water.com/article/163008.htm

使用Vuex的时候,通常会实例化Store类,然后传入一个对象,包括我们定义好的actions、getters、mutations、state等。store的构造函数:

export class Store {
 constructor (options = {}) {
  // 若window内不存在vue,则重新定义Vue
  if (!Vue && typeof window !== 'undefined' && window.Vue) {
   install(window.Vue)
  }

  if (process.env.NODE_ENV !== 'production') {
   // 断言函数,来判断是否满足一些条件
   // 确保 Vue 的存在
   assert(Vue, `must call Vue.use(Vuex) before creating a store instance.`)
   // 确保 Promsie 可以使用
   assert(typeof Promise !== 'undefined', `vuex requires a Promise polyfill in this browser.`)
   assert(this instanceof Store, `store must be called with the new operator.`)
  }

  // 解构赋值,拿到options里的plugins和strict
  const {
   plugins = [],
   strict = false
  } = options

  // 创建内部属性
  // 标志一个提交状态,作用是保证对 Vuex 中 state 的修改只能在 mutation 的回调函数中,而不能在外部随意修改 state
  this._committing = false 
  // 用来存储用户定义的所有的actions
  this._actions = Object.create(null)
  this._actionSubscribers = []
  // 用来存储用户定义所有的mutatins
  this._mutations = Object.create(null)
  // 用来存储用户定义的所有getters 
  this._wrappedGetters = Object.create(null)
  // 用来存储所有的运行时的 modules
  this._modules = new ModuleCollection(options)
  this._modulesNamespaceMap = Object.create(null)
  // 用来存储所有对 mutation 变化的订阅者
  this._subscribers = []
  // 一个 Vue对象的实例,主要是利用 Vue 实例方法 $watch 来观测变化的
  this._watcherVM = new Vue()

  // 把Store类的dispatch和commit的方法的this指针指向当前store的实例上
  const store = this
  const { dispatch, commit } = this
  this.dispatch = function boundDispatch (type, payload) {
   return dispatch.call(store, type, payload)
  }
  this.commit = function boundCommit (type, payload, options) {
   return commit.call(store, type, payload, options)
  }

  // 是否开启严格模式
  this.strict = strict

  const state = this._modules.root.state

  // Vuex的初始化的核心,其中,installModule方法是把我们通过options传入的各种属性模块注册和安装;
  // resetStoreVM 方法是初始化 store._vm,观测 state 和 getters 的变化;最后是应用传入的插件。
  installModule(this, state, [], this._modules.root)

  resetStoreVM(this, state)
  plugins.forEach(plugin => plugin(this))

  const useDevtools = options.devtools !== undefined ? options.devtools : Vue.config.devtools
  if (useDevtools) {
   devtoolPlugin(this)
  }
 }

Vuex本身是单一状态树,应用的所有状态都包含在一个大对象内,随着我们应用规模的不断增长,这个Store变得非常臃肿。为了解决这个问题,Vuex允许我们把store分模块。每一个模块包含各自的state、mutations、actions和getters,甚至还可以嵌套模块。

接下来看installModule方法:

function installModule (store, rootState, path, module, hot) {
 // 通过path数组的长度判断是否为根
 const isRoot = !path.length
 const namespace = store._modules.getNamespace(path)

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

 // 第一次调用时,path为空,不进入if
 // 递归调用installModule安装子模块时,将执行该代码块
 if (!isRoot && !hot) {
  const parentState = getNestedState(rootState, path.slice(0, -1))
  // 模块名
  const moduleName = path[path.length - 1]
  // 把当前模块的state添加到parentState中。具体解析见下
  store._withCommit(() => {
   Vue.set(parentState, moduleName, module.state)
  })
 }

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

 // 对mutations、actions、getters进行注册
 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)
 })

 // 遍历modules,递归调用installModule安装子模块
 module.forEachChild((child, key) => {
  installModule(store, rootState, path.concat(key), child, hot)
 })
}
store的_withCommit方法定义是这样的:

 _withCommit (fn) {
  const committing = this._committing
  this._committing = true
  fn()
  this._committing = committing
 }

Vuex中所有对state的修改都会用_withCommit函数包装,保证在同步修改state的过程中this._committing的值始终为true。这样当我们观测 state的变化时,如果this._committing的值不为true,则能检查到这个状态修改是有问题的。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
一个JavaScript继承的实现
Oct 24 Javascript
XHTML下,JS浮动代码失效的问题
Nov 12 Javascript
Javascript常考语句107条收集
Mar 09 Javascript
Jquery 扩展方法
May 06 Javascript
Eclipse下jQuery文件报错出现错误提示红叉
Jan 13 Javascript
jQuery控制文本框只能输入数字和字母及使用方法
May 26 Javascript
node中Express 动态设置端口的方法
Aug 04 Javascript
探究react-native 源码的图片缓存问题
Aug 24 Javascript
通过fastclick源码分析彻底解决tap“点透”
Dec 24 Javascript
vue cli使用融云实现聊天功能的实例代码
Apr 19 Javascript
Node.js 多进程处理CPU密集任务的实现
May 26 Javascript
layui(1.0.9)文件上传upload,前后端的实例代码
Sep 26 Javascript
vue store之状态管理模式的详细介绍
Jun 13 #Javascript
微信小程序页面间跳转传参方式总结
Jun 13 #Javascript
微信小程序位置授权处理方法
Jun 13 #Javascript
json数据格式常见操作示例
Jun 13 #Javascript
微信小程序实现渐入渐出动画效果
Jun 13 #Javascript
微信小程序前端自定义分享的实现方法
Jun 13 #Javascript
javascript数组常见操作方法实例总结【连接、添加、删除、去重、排序等】
Jun 13 #Javascript
You might like
当年上海收录机产品生产,进口和价格情况
2021/03/04 无线电
php 函数使用方法与函数定义方法
2010/05/09 PHP
php ob_flush,flush在ie中缓冲无效的解决方法
2010/05/09 PHP
php带密码功能并下载远程文件保存本地指定目录 修改加强版
2010/05/16 PHP
用jscript实现新建和保存一个word文档
2007/06/15 Javascript
Prototype RegExp对象 学习
2009/07/19 Javascript
script标签的 charset 属性使用说明
2010/12/04 Javascript
javascript 原型继承介绍
2011/08/30 Javascript
教你用AngularJS框架一行JS代码实现控件验证效果
2014/06/23 Javascript
JavaScript转换二进制编码为ASCII码的方法
2015/04/16 Javascript
JS选项卡动态替换banner图片路径的方法
2015/05/11 Javascript
JavaScript中的toLocaleDateString()方法使用简介
2015/06/12 Javascript
javascript实现网页子页面遍历回调的方法(涉及 window.frames、递归函数、函数上下文)
2015/07/27 Javascript
JavaScript实现点击按钮就复制当前网址
2015/12/14 Javascript
基于JavaScript将表单序列化类型的数据转化成对象的处理(允许对象中包含对象)
2015/12/28 Javascript
jQuery操作属性和样式详解
2016/04/13 Javascript
详解html-webpack-plugin用法全解
2018/01/22 Javascript
layer ui 导入文件之前传入数据的实例
2019/09/23 Javascript
js找出5个数中最大的一个数和倒数第二大的数实现方法示例小结
2020/03/04 Javascript
Python设计模式之观察者模式实例
2014/04/26 Python
python通过自定义isnumber函数判断字符串是否为数字的方法
2015/04/23 Python
将TensorFlow的模型网络导出为单个文件的方法
2018/04/23 Python
Python实现读取SQLServer数据并插入到MongoDB数据库的方法示例
2018/06/09 Python
python全栈知识点总结
2019/07/01 Python
python实现图像拼接功能
2020/03/23 Python
Python requests上传文件实现步骤
2020/09/15 Python
世界排名第一的运动鞋市场:Flight Club
2020/01/03 全球购物
银行实习自我鉴定
2013/10/12 职场文书
新学期家长寄语
2014/01/19 职场文书
党员“四风”方面存在问题及整改措施
2014/09/24 职场文书
学生会感恩节活动方案
2014/10/11 职场文书
个人纪律作风整改措施思想汇报
2014/10/12 职场文书
好媳妇事迹材料
2014/12/24 职场文书
初中政治教学工作总结
2015/08/13 职场文书
2016干部作风整顿心得体会
2016/01/22 职场文书
接收函
2019/04/22 职场文书