vuex

The core concept

  • State Indicates the status and data
  • Mutations is a function of changing state
  • Actions Asynchronous operations
  • Store A container containing the above concepts

The test case

store/index.js

import Vue from 'vue'
import Vuex from './my-vuex.js'

Vue.use(Vuex)

export default new Vuex.Store({
    state: {
        counter: 1
    },
    mutations: {
        add(state) {
            state.counter++
        }
    },
    actions: {
        add({ commit }) {
            setTimeout(() = > {
                commit('add')},1000)}},getters: {
        doubleCounter(state) {
            return state.counter * 2}})}Copy the code
<p @click="$store.commit('add')">counter: {{$store.state.counter}}</p> 
<p @click="$store.dispatch('add')">async counter: {{$store.state.counter}}</p>
<p>Double: {{$store. Getters. DoubleCounter}}</p>
Copy the code

Task analysis

  • Implement the plugin
  • To achieve the Store class
    • Maintain a reactive state
    • Implement the commit ()
    • Realize the dispatch ()
    • getters
  • Mount $store

Initialize: Store declaration, install implementation, my-vuex.js:

let Vue
class Store {
    constructor(options = {}) {
        this._vm = new Vue({
            data: {
                $$state: options.state
            }
        })
    }
    get state() {
        return this._vm._data.$$state
    }
    set state(v) {
        // console.error('please use replaceState to reset state')
        return}}function install(_Vue) {
    Vue = _Vue
    Vue.mixin({
        beforeCreate() {
            if (this.$options.store) {
                Vue.prototype.$store = this.$options.store
            }
        }
    })
}
export default {
    Store,
    install
}
export default { Vuex, install }
Copy the code

Implement COMMIT: obtain and perform mutation based on the type passed in by the user

class Store {
    constructor(options = {}) {
        this._mutation = options.mutations || {}
        this.commit = this.commit.bind(this)}coommit(type, payload) {
        const mutation = this._mutations[type]
        if(! mutation) {// console.error(`unknown mutation type: ${type}`)
            return
        }
        mutation(this.state, payload)
    }
}
Copy the code

Implement actions: Retrieve and execute actions based on the type passed in by the user

class Store {
    constructor(options = {}) {
        this._actions = options.actions || {}
        this.dispatch = this.dispatch.bind(this)}dispatch(type, payload) {
        const action = this._actions[type]
        if(! action) {// console.error(`unknown action type: ${type}`)
            return
        }
        action(this, payload)
    }
}
//
class Vuex {
    constructor(options = {}) {
        this._actions = options.actions || {}
        this.dispatch = this.dipatch.bind(this)}dispatch(type, payload) {
        const action = this._actions[type]
        if(! action) {console.error(`unknown action type: ${type}`)
            return
        }
        action(this, payload)
    }
}
Copy the code

Implement getters

class Store {
    constructor(options = {}) {
        this._wrapperGetters = options.getters || {}
        this.getters = {}
        const computed = {}
        const store = this
        // Functions in computed attributes take no parameters and are wrapped in a layer
        Object.keys(store._wrapperGetters).forEach(key= > {
            const fn = store._wrapperGetters[key]
            computed[key] = function () {
                return fn(store.state)
            }
            Object.defineProperty(store.getters, key, {
                get: () = > {
                    // Execute in computed
                    return store._vm[key]
                }
            })
        })
        this._vm = new Vue({
            data: {
                $$state: options.state
            },
            computed
        })
    }
}
Copy the code

Source github address