手写简版vuex | 8月更文挑战

这是我参与8月更文挑战的第2天,活动详情查看:8月更文挑战

0. 之前写过一篇关于vuex的使用,如果不熟悉的小伙伴请移步这里vuex的使用

1. vuex是集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以可预测的方式发生变化。

2. 核心概念

  1. state状态、数据、
  2. mutation更改状态的函数(唯一的只能通过mutation来修改)
  3. actions异步操作state
  4. store容器,包含以上所有的容器

2. 创建

import Vue from 'vue'
import Vuex from 'vuex'
//vuex是一个插件
//所以呢在它内部应该有install方法
Vue.use(Vuex)

export default new Vuex.Store({
  state: {
      age: 1
  },
  mutations: {
      // state来自哪里
      add(state){
          state.age ++
      }
  },
  actions: {
      // 此处的contex是什么
      add(ctx){
          setTimeout(()=>{
              ctx.commit('add')
          },1000)
      }
  },
  modules: {
  }
})
复制代码

3. 代码实现

//咱们要实现一个插件
//注意跟vue-router不同的是,咱们实例化的时候是new Vuex.Store(options)
//因此呢我们要有一个Store的类
let Vue;
class Store{
    constructor(options){
    
        this._mutations = options.mutations;
        this._actions = options.actions;
        //下面这种写法是最容易想到的,但是这样就可以直接修改state了
        //就不能做到可预测的修改状态了
        //所有我们可以写个静态属性访问器
        // this.state = new Vue({
        //     data(){
        //         return optins.state
        //     }
        // })
        //所有我们用这种写法
        this.$state = new Vue({
            data(){
                return {
                //这样做不让vue直接代理state属性
                    _state: optins.state
                }
            }
        })
        //绑定this指向
        this.commit = this.commit.bind(this);
        this.dispatch = this.dispatch.bind(this);
    }
    //静态属性访问器
    get state(){
        return this.$state._data._state
    }
    set state(val){
        console.warn('禁止直接修改state')
    }
    
    commit(type, payload){
        const mutation = this._mutations[type];
        if(!mutation){
            console.warn('请指定正确的mutation名称')
            return
        }
        mutation(this.state, payload)
    }
    dispatch(type, payload){
        const action = this._actions[type];
        if(!action){
            console.warn('请指定正确的action名称')
            return
        }
        //this就是store实例,这就解释了actions里面的contex是啥,但是这里的this有可能不是指向store,
        //因此上面就绑定了this指向
        action(this, payload)
    }
}
function install(_Vue){
    Vue = _Vue;
    
    //跟vue-router一样在所有组建的实例上都应该有$store,因此我们需要注册$store到组件实例上使用混入
    Vue.mixin({
        beforeCreate(){
            //这个options及时new Vue的时候传入的options
            var options = this.$options;
            // store injection
            if (options.store) {
               this.$store = options.store;
            } else if (options.parent && options.parent.$store) {
               this.$store = options.parent.$store;
            }
        
         }
    })
    

}
// 并且呢用默认导出一个对象里面包含这个类以及insatll方法{Store, insatll}
复制代码

4. 其实这真的是最简单的原理实现,也能说明问题,当然真正的源码比我们这复杂的多,实现最简单版本,也是有利于我们在工作中对问题的思考已经思路开拓

5. 咱们再来思考几个问题

  1. vuex里面的getter计算属性如何实现
  2. 如何实现modules
  3. 在不同modules里面定义相同的mutation会触发哪个呢

总结:每天进步一点点 总会从超鬼变成超神的

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享