简单Vuex底层原理实现

336 阅读1分钟
let Vue;

class Store{
  constructor(options){// options就是new Vuex.Store传入的参数
    // 1.使用vue实列来实现响应式变化,保证状态更新会刷新视图
    this.vm = new Vue({//1.data会被使用Object.defineProperty重新定义
      date: {
        state: options.state
      }
    });
    // 2.解析options.getters,它是一个对象,里面都是函数
    this.getters={};
    Object.keys(options.getters).forEach(getterName=>{
      Object.definePropery(this.getters, getterame,{
        get:()=>{return options.getters[getterName](this.state)}
      })
    });
    //3.解析options.mutations
    this.mutations = {};
    Object.keys(options.mutations).forEach(mutationsName=>{
      this.mutations[mutationsName] = (payload)=>{
        options.mutations[mutationsName](this.state, payload)
      }
    });
    // 4.解析options.actions
    this.actions = {};
    Object.keys(options.actions).forEach(actionsName=>{
      this.actions[actionsName] = (payload)=>{
        options.actions[actionsName](this, payload)
      }
    });
  }
  get state(){ //1.获取实例上的state——>store.state
    // 1.相当于this.state = this.vm.state
    return this.vm.state
  }
  // 3.用箭头函数的目的是让this一直指向Store——>$store.commit
  commit = (mutationName, payload) => {this.mutations[mutationsName](payload)};
  // 4.$store.dispatch
  dispatch = (actionName, payload) =>{this.actions[actionsName](payload)}
}

// 每一个插件都有一个install函数,主要就是只有当前的实例才能使用这个插件
const install = (_Vue) => { //_Vue是vue的构造函数
  // 使得当前插件不再依赖Vue而是通过用户把Vue传过来,import vue打包的时候体量太大?
  Vue = _Vue; //传过来的vue的构造函数
  // 下载不是下载到vue的原型上,我们只想给当前实列下的组件使用
  // 使用mixin,抽离组件的公共逻辑,每个组件(vue)调用beforeCreate都会执行里面的方法
  // 值得注意的是,main.js(父)有个vue,app.vue也有个vue(子)
  Vue.mixin({
    beforeCreate(){
      // console.log(this.name)//root-->app-->app的子...
      // 为了让所有子组件使用store,就把root的store属性放在每个组件的实列上
      if(this.$options.store){//是root,这个root是有store的
        this.$store = this.$options.store
      }else{// 是子组件
        this.$store = this.$parent && this.$parent.$store
      }
    }
  }) 
}

export default{
  Store,
  install
}