手动实现vuex

513 阅读1分钟

前言

手动实现一个vuex,简单了解其原理

vuex的基本使用

// 1.Vue.use注册vuex
Vue.use(Vuex)

// 2.创建store实例
const store = new Vue.Store({
 // 数据
 state: {
    counter: 0
  },
  // 自动计算,类似计算属性
  getters: {
    doubleCounter(state) {
      return state.counter * 2
    }
  },
  // 同步修改数据
  mutations: {
    add(state) {
      state.counter++
    }
  },
  // 异步
  actions: {
    add({commit}) {
      setTimeout(()=>{
        commit('add')
      },1000)
    }
  },
})

// 3.传入Vue的options选项中
new Vue({
   store,
   // ...
})

// 4.在页面中使用
<template>
  <div class="home">
    <p @click="$store.commit('add')">counter: {{$store.state.counter}}</p>
    <p @click="$store.dispatch('add')">async counter: {{$store.state.counter}}</p>
    <p >getters counter: {{$store.getters.doubleCounter}}</p>
  </div>
</template>

vuex实现

思路

  • vuex在use之后,会在每个vue实例上,都存在$store方法,所以可以通过beforeCreate时,在原型上添加
  • state上的数据都是响应式的,可以通过new Vue来实现

代码

let Vue
// 方法在use的时候会执行,参考上一篇文章
function install(_Vue) {
    Vue = _Vue
    Vue.minx({
        beforeCreate() {
            if(this.$options.store) {
                Vue.prototype.$store = this.$options.store
            }
        }
    })
}

class Store {
    constructor(options) {
        this.getters = {}
        const computed = {}
        Object.keys(options.getters).forEach(key=>{
          // 封装计算属性,传入给vue实例
          computed[key] = () => options.getters[key](this.state)
          // 定义getters属性的get方法,访问该对象的属性时,就去访问vue的计算属性
          Object.defineProperty(this.getters, key, {
            get: () => this._vm[key],
            enumerable: true // for local getters
          })
        })
    
        this._vm = new Vue({
            data: {
                $$state: options.state
            }
        })
        this._mutations = options.mutations
        this._actions = options.actions
        
        // 绑定this
        this.commit = this.commit.bind(this)
        this.dispatch = this.dispatch.bind(this)
    }
    
    // 执行mutations同步方法
    commit(type, payload) {
        const entry = this._mutations[type]
        if(!entry) {
            console.error('not function')
        }
        entry(this.state, payload)
    }
    
    // 执行actions异步方法
    dispatch(type, payload) {
        const entry = this._actions[type]
        if(!entry) {
            console.error('not function')
        }
        entry(this, payload)
    }
    
    get state() {
        return this._vm._data.$$state
    }
    
    set state(v) {
        console.error('not set')
    }
}
export default {
    install,
    Store
}

最后

简易版的vuex算是完成,周末愉快。