1 the use of

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    counter: 0
  },
  mutations: { 
    add(state) {
      state.counter++
    }
  },
  actions: { 
    add({ commit }) {
      setTimeout(() = > {
        commit('add')},1000); }},modules: {
  }
})

<template>
  <div id="app">
    <p @click="$store.commit('add')">counter: {{$store.state.counter}}</p>
    <p @click="$store.dispatch('add')">async counter: {{$store.state.counter}}</p>
  </div>
</template>
Copy the code

2. Code implementation

let _Vue
class Store {

    constructor(options) {
        this._mutations = options.mutations
        this._actions = options.actions
        this._getters = options.getters
        this.getters = {}
        // Use vUE instances to implement responsiveness
        this._vm = new _Vue({
            data() {
                return {
                    $$state: options.state // Add $sign to data that cannot be externally used directly with _vm.$$state}}})this.commit = this.commit.bind(this) // Bind must be assigned, otherwise the this binding is invalid
        this.dispatch = this.dispatch.bind(this)}// Use es6 get set method to protect data effectively
    get state() {$$state = this._vm._data.$$state = this._vm
        return this._vm._data.$$state
    }

    set state(val) {
        console.error("State cannot be set directly")}commit(type , playload){
       const fn = this._mutations[type] 
       console.log(fn)
       if(! fn) {// throw Error('unknow mutation')
       }else {
        fn( this.state, playload)
       }
    }
    dispatch(type , playload){
        const fn = this._actions[type]
        if(! fn) {// throw Error('unknow action')
        } else {
            return fn(this,playload)
        }
    }
 
}

function install(Vue) {
    _Vue = Vue // Record the global instance
    Vue.mixin({
        beforeCreate(){
            if(this.$options.store) {
                Vue.prototype.$store = this.$options.store
            } 
        }
    })
}
 
export default {
    Store,
    install
}
Copy the code

3. The getters


/ / use
Vue.use(Vuex)

export default new Vuex.Store({
    state : {
        counter : 2
    }, 
    getters : {
        total(state) {
            return "Together." + state.counter
        }
    }
})
<template>
  <div id="app"> 
    <p >getters total: {{$store.getters.total}}</p>
  </div>
</template>


 constructor(options) {
        this._getters = options.getters
        this.getters = {}
        let _this = this 
        for (const key in this._getters) { 
                const fn = this._getters[key];   
                Object.defineProperty(this.getters,key, {
                    get : () = > {
                        return fn(_this.state)
                    }
                })
        }
    }
Copy the code

4. Getters cache implementation


 this._getters = options.getters
        this.getters = {}

        let _this = this
        let computed = {}
        for (const key in this._getters) { 
                const fn = this._getters[key]
                computed[key] = function() {
                    return fn(_this.state)
                }
                Object.defineProperty(this.getters,key, {
                    get : () = > {
                        return _this._vm[key]
                    }
                })
        } 

        // Use vUE instances to implement responsiveness
        this._vm = new _Vue({
            data() {
                return {
                    $$state: options.state // Add $sign to data that cannot be externally used directly with _vm.$$state
                }
            },
            computed // Implement caching using vUE computed
        })
Copy the code