我把 vuex 的源码 clone 下来了,搞明白了这些问题

1,080 阅读1分钟

解决了那些困惑

  1. 为什么组件能够通过 this.$store.state 访问到 vuex 注册的数据
  2. 执行 this.$store.commit() 能够触发 相应的 mutation 来更新 state

首先看一下,vuex 的基本使用

  1. 首先要下载插件,
  2. Vue.use(vuex) 注册插件
  3. 声明实例挂载到根组件
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: store,
})
  1. 然后可以在组件中访问
methods: {
  increment() {
    this.$store.commit('increment')
    console.log(this.$store.state.count)
  }
}

Vuex.use(vuex) 发生了什么

首先该方法是调用了插件的 install 方法

install 方法在目录 /src/store.js

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

然后查看 applyMixin 方法干了什么 (只取源码中核心代码), 能通过 this.$store.state 访问的关键

export default function(Vue) {
    // 全局混入一个基本钩子函数,在每个组件实例构建前
    // 执行 vuexInit 初始化函数
    Vue.mixin({ beforeCreate: vuexInit})
    
    function vuexInit () {
        const options = this.$options
        // store injection
        // 给每个组件的 $store, 以便能够通过,this.$store.state 拿到值
        // 做的操作就是,如果组件有 store 配置项,直接把 this.$store 赋值为  options.store, 没有的话就从父组件中取
        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
        }
      }
}

执行 commiit 触发为什么可以触发响应的 mutation 更新 state

简化一下源码中的相关代码

export class Store {
    constructor (options = {}) {
      // 首先拿到实例中的 commit ,然后让调用本身的 commit 函数
      const { commit } = this;
      this.commit = function boundCommit (type, payload, options) {
        return commit.call(store, type, payload, options)
      }
    }
    commit (_type, _payload, _options) {
      // 我猜 这句代码就是从 mutations 对象里面,拿到所有的 mutation
      const entry = this._mutations[type]
      // 执行 type 对应的 mutations
      entry.forEach(function commitIterator (handler) {
        handler(payload)
      })
    }
}

最基本的应该就是这个吧,源码还是得慢慢看,不能急啊,烦请过路大佬批评指正

这里附上vuex源码