源码阅读vuex

源码阅读vuex

Vue.use

在vue项目中使用路由时,需要通过Vue.use(Vuex)注册状态管理。

在vue源码文件vue/src/core/index.js中,调用了initGlobalAPI(Vue)方法,
vue/src/core/global-api/index.js中,定义并导出了initGlobalAPI方法,
initGlobalAPI方法中调用了initUse(Vue),在vue/src/core/global-api/use.js中,找到initUse
在这里定义了Vue.use

export function initUse (Vue: GlobalAPI) {
   
  Vue.use = function (plugin: Function | Object) {
   
    // 获取已经注册的插件列表
    const installedPlugins = (this._installedPlugins || (this._installedPlugins = []))
    // 避免重复注册
    if (installedPlugins.indexOf(plugin) > -1) {
   
      return this
    }

    // 获取其他参数
    const args = toArray(arguments, 1)
    // 向参数数组首部推入当前vue实例
    args.unshift(this)
    // 当组件有install方法时调用install,或者当组件本身是一个可调用的方法时,调用组件方法,以此完成注册动作
    if (typeof plugin.install === 'function') {
   
      plugin.install.apply(plugin, args)
    } else if (typeof plugin === 'function') {
   
      plugin.apply(null, args)
    }
    // 向已注册数组增加注册组件
    installedPlugins.push(plugin)
    
    return this
  }
}

vue/src/shared/util.js中,找到toArray方法,用于将一个类数组对象转换成数组。

export function toArray (list: any, start?: number): Array<any> {
   
  start = start || 0
  let i = list.length - start
  const ret: Array<any> = new Array(i)
  while (i--) {
   
    ret[i] = list[i + start]
  }
  return ret
}

install + applyMixin

在vuex源码vue-router/src/store.js中导出了install方法。

import applyMixin from './mixin'
export function install (_Vue) {
   
  // 避免重复注册
  if (Vue && _Vue === Vue) {
   
    if (__DEV__) {
   
      console.error(
        '[vuex] already installed. Vue.use(Vuex) should be called only once.'
      )
    }
    return
  }
  Vue = _Vue
  applyMixin(Vue)
}

install 做了重复注册校验,并调用了applyMixin方法,applyMixin来自vue-router/src/mixin.js

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)
    }
  }

  /**
   * Vuex init hook, injected into each instances init hooks list.
   */

  function vuexInit () {
   
    const options = this.$options
    // store injection
    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
    }
  }
}

applyMixin 做了一个版本判断,如果vue版本大于等于2,则在vue的beforeCreate生命周期混入一个vuexInit方法,如果版本小于2,则重写了vue的_init方法,将vuexInit加到_init参数options的init属性上,然后执行原来的_init内容。

vuexInit的内容也很简单,判断当前vue实例上有没有store,有的话就将 s t o r e 指 向 t h i s . store指向this. storethis.options.store,如果这个store是一个方法,就执行拿到它的结果再赋值,如果当前vue实例没有store,就从父组件拿。这就保证了全局只有一个sotre,达到所有组件共用状态的目的。

Store

来看一下通常我们是怎么使用vuex的:

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store({
   
  state: {
   
    count: 0
  },
  mutations: {
   
    increment (state) {
   
      state.count++
    }
  }
})
new Vue({
   
  el: '#app',
  store
})

可以看到Vue实例化传入的store对象,是通过new Vuex.Store({})实例化生成的,那么接下来,就看一下Store构造函数。

源码跟install方法在同一个文件中:vue-router/src/store.js

export class Store {
   
  constructor (options = {
   }) {
   
    // 如果还未注册,在有window.Vue的情况下,会自动注册
    if (!Vue && typeof window !== 'undefined' && window.Vue) {
   
      install(window.Vue)
    }
    // 开发环境下的一些报错
    if (__DEV__) {
   
      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 {
   
      // 插件数组,vuex 插件暴露出每次 mutation 的钩子
      plugins = [],
      // 严格模式设置,在严格模式下,无论何时发生了状态变更且不是由 mutation 函数引起的,将会抛出错误。
      strict = false
    } = options

    // 各种内部属性初始化
    this._committing = false // 用来判断严格模式下是否是用mutation修改state
    this._actions = Object.create(null)
    this._actionSubscribers = []
    this._mutations = Object.create(null)
    this._wrappedGetters = Object.create(null)
    this._modules 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值