vuex原理

227 阅读1分钟

Vuex集中式状态管理应用的所有组件的状态,并以相应的规则保证状态以可预测的方式发生变化

一.安装

 vue add vuex

二.核心概念

  1. state 状态、数据
// 保存应用状态
export default new Vuex.Store({
  state: { counter:0 },
})
  1. mutations更改状态的函数
// mutations用于修改状态
export default new Vuex.Store({
  mutations: {
    add(state) {
      state.counter++
} }
})
  1. actions 异步操作
// 添加业务逻辑,类似于controlle
export default new Vuex.Store({
    actions: {
        add({ commit }) {
            setTimeout(() => {
} }
})
  1. store是包含以上概念的容器

三.vuex原理解析

需求分析

  1. 实现一个插件:声明Store类,挂载$store
  2. 创建响应式的state,保存mutations、actions和getters
  3. 实现commit根据用户传入type执行对应mutation
  4. 实现dispatch根据用户传入type执行对应action,同时传递上下文
  5. 实现getters,按照getters定义对state做派生

源码实现

步骤一:初始化:Store声明、install实现

 
let Vue;
class Store {
  constructor(options = {}) {
    this._vm = new Vue({
      data: {
        ?state:options.state
      }
    }); 
  }
  get state() {
    return this._vm._data.?state
  }
  set state(v) {
    console.error('please use replaceState to reset state');
  } }
function install(_Vue) {
  Vue = _Vue;
  Vue.mixin({
    beforeCreate() {
      if (this.$options.store) {
        Vue.prototype.$store = this.$options.store;
      } }
  }); }
export default { Store, install };

步骤二: 实现commit:根据用户传入type获取并执行对应mutation

 
class Store {
  constructor(options = {}) {
    // 保存用户配置的mutations选项
    this._mutations = options.mutations || {}
  }

  commit(type, payload) {
    // 获取type对应的mutation
    const entry = this._mutations[type]
    if (!entry) {
      console.error(`unknown mutation type: ${type}`);
      return
    }
    // 指定上下文为Store实例
    const store = this
    const {commit} = store
    this.commit = function boundCommit(type, payload) {
      commit.call(store, type, payload)
    }
    // 传递state给mutation
    entry(this.state, payload);
  }
}

步骤三: 实现actions:根据用户传入type获取并执行对应action

 
class Store {
  constructor(options = {}) {
    // 保存用户编写的actions选项 
    this._actions = options.actions || {}
    // 绑定commit上下文否则action中调用commit时可能出问题!! 
    // 同时也把action绑了,因为action可以互调
    const store = this
    const {action} = store
    this.action = function boundAction(type, payload) {
      return action.call(store, type, payload)
    }
  }

  dispatch(type, payload) {
    // 获取用户编写的type对应的action const entry = this._actions[type]
    if (!entry) {
      console.error(`unknown action type: ${type}`);
      return
    }
    // 异步结果处理常常需要返回Promise
    return entry(this, payload);
  }
}

步骤四: 实现getters,根据用户传入的方法名称执行

 
class Store {
  constructor(options = {}) {
    // 保存用户编写的getters选项 
    this._wrappedGetters = options.getters || {}
    // 定义computed选项
    const computed = {}
    // 给用户暴露一个可以访问的getters
    this.getters = {}
    // 绑定this指向
    const store = this
    // 遍历getters
    Object.keys(this._wrappedGetters).forEach( key => {
        // 获取用户定义的getter
        const fn = store._wrappedGetters[key]
        // 转化为computed可以使用的无参数的形式
        computed[key] = function() {
            return fn(store.state)
        }
        // 为getters定义只读属性
        Object.defineProperty(store.getters, key, {
            get: () => store.$vm[key]
        })
    })
     this._vm = new Vue({
      data: {
        ?state:options.state
      },
      computed
    }); 
  }
}