会用就行?一起来实现个自己的Vuex吧!

234 阅读1分钟

Vuex想必大家都用过,是一个非常好用的,专为Vue.js应用程序开发的状态管理模式,今天就带着大家一步步来实现一个很很很简单的Vuex demo,话不多说,先上代码:

我们要实现的功能就是Vuex的四个核心概念:State、Getters、Mutations、Actions,如下代码所示:

import Vue from 'vue'
// import Vuex from 'vuex'
//替换成自己实现的Vuex
import Vuex from 'myvuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 1,
    msg: 'hello 五条杠!'
  },
  getters: {
  	reverseMsg(state) {
      return state.msg.split('').reverse().join('')
    }
  },
  mutations: {
  	increase(state, num) {
    	state.count += num
    }
  },
  actions: {
    increaseAsync(context, num)
  	setTimeout(() => {
    	context.commit('increase', num)
    }, 1000)
  }
})

在视图当中使用:

<template>
  <div id="app">
    <h1>Vuex demo</h1>
    <div>count: {{$store.count}}</div>
    <div>msg: {{$store.msg}}</div>
    <h2>Getter</h2>
    <div>reverseMsg: {{$store.getters.reverseMsg}}</div>
    <h2>Mutation</h2>
    <button @click="$store.commit('increase')">Increase</button>
    <h2>Action</h2>
    <button @click="$store.dispatch('increaseAsync')">IncreaseAsync</button>
  </div>
</template>

接下来就是让上面的代码跑起来!

首先我们知道,Vuex是以插件的形式使用的,即Vue.use(Vuex),所以Vuex必须有一个install方法,另外需要注意的是,Vuex生成实例的方式是new Vuex.Store(...),所以框架结构就是这样的:

class Store {...}
function install(Vue) {...}

export default {
  Store,
  install
}

不知道为什么要有一个install方法的同学,我在Vue官网截了一张图:

如果想了解更多插件的知识先移步至vue官网 cn.vuejs.org/v2/guide/pl…

下面就来实现install方法:

let _Vue = null
function install(Vue) {
_Vue = Vue
  Vue.mixin({
    beforeCreate() {
      if (this.$options.store) {
        Vue.prototype.$store = this.$options.store
      }
    }
  })
}

可以看到,install的实现非常简单,第一就是先将传入的Vue构造函数记录到全局变量_Vue中,供接下来的准备实现的Store类来使用,第二就是就是将Vue实例上的$options.store对象挂载到Vue的原型上,这里的this就是Vue实例,这里使用Vue.mixin全局混入,所以必须加个判断,因为只有mian.js里面的那个实例才有$options.store。

然后就是实现Store类:

class Store {
  constructor(options) {
    // 先将传入的参数解构出来
    const {
      state = {},
      getters = {},
      mutations = {},
      actions = {}
    } = options || {}
    
    // state是响应式的,所以用Vue.observable进行处理
    this.state = _Vue.observable(state)
    
    // 实现getters
    this.getters = Object.create(null)
    Object.keys(getters).forEach(key => {
      Object.defineProperty(this.getters, key, {
        get: () => getters[key](state)
      })
    })
    
    // 将mutations和actions记录到“私有”变量中
    this._mutations = mutations
    this._actions = actions
    
    // 实现commit
    this.commit = function(type, payload) {
      this._mutations[type](this.state, payload)
    }
    
    // 实现dispatch
    this.dispatch = function(type, payload) {
      this._actions[type](this, payload)
    }
  }
}

可以看到,整体的代码非常简单,没啥可说的... 权当是练手实现Vue的插件功能,也能看到即使是Vuex这么流行的工具,其基本原理也是非常的简单,不知道各位是不是对源码阅读更加有信心了哈哈。

最后,祝各位圣诞快乐哦!