手写mini版vuex响应式数据仓库

前言~~不喜欢手写原理的程序员不是好的程序员

根据vuex官网的使用,下面来实现以下基础的vuex中心化数据响应式原理

1.首先来看一下 store注册

store注册使用了vue的插件机制,use方法会调用插件的install方法

用过store的我们可以得知,在vue中每个实例的每个方法都可以通过this.$store 调用数据仓库,

这样我们就可以得出,我们的vuex插件是有install方法,主要实现了store的全局混入,我们这里利用一些vue的mixin全局混入,beforeCreate生命周期一开始就对vue组件实例注入到this.$store中

/**
* store.js - store 注册
*/
let Vue

// vue 插件必须要这个 install 函数
export function install(_Vue) {
  // 拿到 Vue 的构造器,存起来
  Vue = _Vue
  // 通过 mixin 注入到每一个vue实例 👉 https://cn.vuejs.org/v2/guide/mixins.html
  Vue.mixin({ beforeCreate: vuexInit })
  
  function vuexInit () {
    const options = this.$options
    // 这样就可以通过 this.$store 访问到 Vuex 实例,拿到 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
    }
  }
}

 

2. 实现vuex的响应式功能

说到响应式功能,我们是否可以利用vue的响应式原理呢

 

export class Store {
  constructor(options = {}) {
    resetStoreVM(this, options.state)
  }
  
  get state () {
    return this._vm._data.$$state
  }
}

function resetStoreVM(store, state) {
  // 因为 vue 实例的 data 是响应式的,正好利用这一点,就可以实现 state 的响应式
  store._vm = new Vue({
    data: {
      $$state: state
    }
  })
}

 

3. vuex的衍生数据,getters

class Store{
    constructor(options={}){

        this.resetStoreVm(options.state)

        const { mutations,actions,getters } = options
        this.options = options
    
        // 我们用 getters 来收集衍生数据 computed
        this.getters = {}
        // 简单处理一下,衍生不就是计算一下嘛,传人 state
        for(let key in getters){
            Object.defineProperty(this.getters,key,{
                get:()=>getters[key](this.state)
            })
        }

   

    }
    get state(){
        return this._vm._data.$$state
    }

    resetStoreVm(state){
        this._vm = new Vue({
            data:{
                $$state:state
            }
        })
    }
 
}

 

4.实现Actions/Mutations

class Store{
    constructor(options={}){

        this.resetStoreVm(options.state)

        const { mutations,actions,getters } = options
        this.options = options
    
        // 我们用 getters 来收集衍生数据 computed
        this.getters = {}
 
        // 简单处理一下,衍生不就是计算一下嘛,传人 state
        for(let key in getters){
            Object.defineProperty(this.getters,key,{
                get:()=>getters[key](this.state)
            })
        }

        // 定义的行为,分别对应异步和同步行为处理
        this.mutations = {}
        this.actions = {}
        for(let key in mutations){
            this.mutations[key] = (payload)=>{
                // 最终执行的就是 this._vm_data.$$state.xxx = xxx 这种操作
                mutations[key](this.state,payload)
            }
        }
        for(let key in actions){
            this.actions[key] = (payload)=>{
                // action 专注于处理异步,这里传入 this,这样就可以在异步里面通过 commit 触发 mutation 同步数据变化了
                actions[key](this,payload)
            }
        }

    }
    get state(){
        return this._vm._data.$$state
    }

    resetStoreVm(state){
        this._vm = new Vue({
            data:{
                $$state:state
            }
        })
    }
    // 触发 mutation 的方式固定是 commit
    commit(name,payload){
        return this.mutations[name](payload)
    }
    // 触发 action 的方式固定是 dispatch
    dispatch(name,payload){
        return this.actions[name](payload)
    }
}

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一杯码农

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值