浅析vuex的原理

8、vuex原理解析

vuex的思想:

Vuex维护着一个全局的对象,使用到单列数据模式,在这个对象中所有的数据都是响应式的,任意属性进行改变,都会让这个属性所有的依赖进行更新,并且只能通过Mutations进行改变。实现了单向数据流。

8.1、vuex的安装

vuex和vue0router的安装方式很一样都是通过vue.use()方法进行安装,内部通过调用install方法进行插件的安装。下面看下vuex的install安装函数。

/*暴露给外部的插件install方法,供Vue.use调用安装插件*/
export function install (_Vue) {
   
 /*避免重复安装(Vue.use内部也会检测一次是否重复安装同一个插件)*/
  if (Vue && _Vue === Vue) {
   
    if (__DEV__) {
   
      console.error(
        '[vuex] already installed. Vue.use(Vuex) should be called only once.'
      )
    }
    return
  }
  /*保存Vue,同时用于检测是否重复安装*/
  Vue = _Vue
   /*将vuexInit混淆进Vue的beforeCreate(Vue2.0)或_init方法(Vue1.0)*/
  applyMixin(Vue)
}

install代码做了两件事

  • 通过Vue变量去防止vuex重复安装
  • 执行applyMixin函数,目的是执行vueinit方法去初始化vuex,Vuex针对Vue1.0与2.0分别进行了不同的处理,如果是Vue1.0,Vuex会将vuexInit方法放入Vue的_init方法中,而对于Vue2.0,则会将vuexinit混淆进Vue的beforeCreacte钩子中。来看一下vuexInit的代码。
export default function (Vue) {
   
  const version = Number(Vue.version.split('.')[0])

  if (version >= 2) {
   
    Vue.mixin({
    beforeCreate: vuexInit })
  } else {
   
    // override init and inject vuex init procedure
    // for 1.x backwards compatibility.
    const _init = Vue.prototype._init
    Vue.prototype._init = function (options = {
   }) {
   
      options.init = options.init
        ? [vuexInit].concat(options.init)
        : vuexInit
      _init.call(this, options)
    }
  } 

function vuexInit () {
   
	//获取vue实例的options
    const options = this.$options
    // store injection
	//如果是根节点则直接执行store或者将store赋值给this.$store
    if (options.store) {
   
      this.$store = typeof options.store === 'function'
        ? options.store()
        : options.store
    } else if (options.parent && options.parent.$store) {
   
	  //子组件直接从父组件中获取$store,这样就保证了所有组件都公用了全局的同一份store
      this.$store = options.parent.$store
    }
  }
}

第一个导出的就是applyMixin函数, vuexInit会尝试从options中获取store,如果当前组件是根组件(Root节点),则options中会存在store,直接获取赋值给 s t o r e 即 可 。 如 果 当 前 组 件 非 根 组 件 , 则 通 过 o p t i o n s 中 的 p a r e n t 获 取 父 组 件 的 store即可。如果当前组件非根组件,则通过options中的parent获取父组件的 storeoptionsparentstore引用。这样一来,所有的组件都获取到了同一份内存地址的Store实例,于是我们可以在每一个组件中通过this.$store愉快地访问全局的Store实例了。

8.2、Store实例化

Store 对象的构造函数接收⼀个对象参数,它包含actions 、 getters 、 state 、 mutations 、 modules 等 Vuex 的核⼼概念。

constructor (options = {
   }) {
   
    // Auto install if it is not done yet and `window` has `Vue`.
    // To allow users to avoid auto-installation in some cases,
    // this code should be placed here. See #731
    /*
      在浏览器环境下,如果插件还未安装(!Vue即判断是否未安装),则它会自动安装。
      它允许用户在某些情况下避免自动安装。
    */
    if (!Vue && typeof window !== 'undefined' && window.Vue) {
   
      install(window.Vue)
    }

    if (process.env.NODE_ENV !== 'production') {
   
      assert(Vue, `must call Vue.use(Vuex) before creating a store instance.`)
      assert(typeof Promise !== 'undefined', `vuex requires a Promise polyfill in this browser.`)
      assert(this instanceof Store, `Store must be called with the new operator.`)
    }

    const {
   
      /*一个数组,包含应用在 store 上的插件方法。这些插件直接接收 store 作为唯一参数,可以监听 mutation(用于外部地数据持久化、记录或调试)或者提交 mutation (用于内部数据,例如 websocket 或 某些观察者)*/
      plugins = [],
      /*使 Vuex store 进入严格模式,在严格模式下,任何 mutation 处理函数以外修改 Vuex state 都会抛出错误。*/
      strict = false
    } = options

    /*从option中取出state,如果state是function则执行,最终得到一个对象*/
    let {
   
      state = {
   }
    } = options
    if (typeof state === 'funct
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值