vue系列--60行代码实现一个简易版的Vuex

一个简单的Vuex实现

回忆一下vuex的一些使用方式,包括:

// $store的方式
this.$store.state.xxx
this.$store.getters.xxx
this.$store.commit('MutationName', data)
this.$store.dispatch('ActionName', data)

// map的方式
computed: {
  ...mapState(['StateName']),
  ...mapGetters(['GetterName'])
}

methods: {
  ...mapMutations(['MutationName']),
  ...mapActions(['ActionName'])
}

实现一个简单的vuex

  1. 写install方法,注册插件,引入Vue,并使用mixin在beforeCreate生命周期里给Vue的原型挂载对象
  2. 定义Store类,将传入的state使用Vue实现响应式
  3. 实现commit方法,即调用mutations的方法,使用响应式的state入参即可
  4. 实现dispatch方法,即调用并返回actions的方法,使用响应式的state入参即可
  5. 实现getters,利用Object.keys遍历传入的getters的key,再利用Object.defineProperty实现get方法
let Vue;

// install方法注册插件
function install(_Vue) {
  Vue = _Vue;

  Vue.mixin({
    beforeCreate() {
      if (this.$options.simplestore) {
        Vue.prototype.$simplestore = this.$options.simplestore;
      }
    }
  });
}

class Store {
  constructor(options) {
    this.state = new Vue({
      data: options.state
    });

    this.mutations = options.mutations;
    this.actions = options.actions;

    options.getters && this.initGetters(options.getters);
  }

  commit = (key, ...data) => {
    const fn = this.mutations[key];
    if (fn) {
      fn(this.state, ...data);
    }
  }

  dispatch = (key, ...data) => {
    const fn = this.actions[key];
    if (fn) {
      return fn({ commit: this.commit, state: this.state }, ...data);
    }
  }

  initGetters(getters) {
    this.getters = {};

    Object.keys(getters).forEach(key => {
      Object.defineProperty(this.getters, key, {
        get: () => {
          return getters[key](this.state);
        }
      })
    })
  }
}

export default {
  install,
  Store
}

源码在github,在src/simple-vuex/index.js,演示在/src/components/simple-vuex-demo.vue里

你可能感兴趣的:(vue系列--60行代码实现一个简易版的Vuex)