The renderings are as follows:

1. Prepare your environment

Initialize the project configuration using vue/ CIL:

NPM install -g@vue /cli // Global installation @vue/cli vue create demo-vue // Create a project

Yarn add vuex Install vuex create a store folder and use:

2. Achieve your purpose

Stroe /index.js contents are as follows :(our purpose is to introduce self-written vuex to realize basic functions of vuex)

import Vue from 'vue'
import Vuex from 'vuex'  
// import Vuex from './myvuex' // Bronze Vuex we implemented
// import Vuex from './myvuexplus' // The silver version of Vuex we implemented

Vue.use(Vuex)  // Run install to mount new vuex. Store to this.$Store

export default new Vuex.Store({
  state: {
    counter: 0.userData: {
      name: 'time'.age: 18}},getters: {
    name(state) {
      return state.userData.name
    }
  },
  mutations: {
    add(state) {
      state.counter++
    },
    updateName(state, payload) {
      state.userData.name = payload
    }
  },
  actions: {
    add({ commit }) {
      setTimeout(() = > {
        commit('add')},1000); }}})Copy the code

Bronze version vuexmyvuex.jsThe code is as follows:

let Vue
class Store {
  constructor(options) {
    this._vm = new Vue({
      data: {
        state: options.state
      }
    })

    let getters = options.getters
    this.getters = {}
    Object.keys(getters).forEach((val) = > {
      Object.defineProperty(this.getters, val, { / / getters response type
        get: () = > {
          return getters[val](this.state)
        }
      })
    })

    this._actions = Object.assign({}, options.actions)
    this._mutations = Object.assign({}, options.mutations)
  }

  // get/set state Objective: To prevent the state from being directly modified externally
  get state() {
    return this._vm.state
  }
  set state(value) {
    console.error('please use replaceState to reset state')
  }

  commit = (funName, params) = > { //this is an execution problem
    // Find the corresponding function in funName in mutations and execute it
    this._mutations[funName](this.state, params)
  }

  dispatch(funName, params) {
    this._actions[funName](this, params)
  }
}

function install(vue) {
  Vue = vue
  vue.mixin({
    beforeCreate () {
      // Mount the new Store() instance to the only root component, this
      if (this.$options? .store) {this.$store = this.$options.store
      } else {
        this.$store = this.$parent && this.$parent.$store
      }
    }
  })
}

export default {
  Store,
  install
}
Copy the code

Bronze version vuexthis.$stroe:

The silver version vuexmyvuexplus.jsThe code is as follows:


let _Vue
const install = function(Vue, opts) {
  _Vue = Vue
  _Vue.mixin({ // Since we have this.$store for each component, we use mixin mode
    beforeCreate () { // Assignment is traversed from the root component to its children, where this is each Vue instance
      if (this.$options && this.$options.store) { // This is the root node
        this.$store = this.$options.store
      } else {
        this.$store = this.$parent && this.$parent.$store
      }
    }
  })
}

class ModuleCollection {
  constructor(opts) {
    this.root = this.register(opts)
  }

  register(module) {
    let newModule = {
      _raw: module._state: module.state || {},
      _children: {}}Object.keys(module.modules || {}).forEach(moduleName= > {
      newModule._children[moduleName] = this.register(module.modules[moduleName])
    })
    return newModule
  }
}

class Store {
  constructor(opts) {
    this.vm = new _Vue({
      data () {
        return {
          state: opts.state // Make the object responsive so the view can be updated}}})this.getters = {}
    this.mutations = {}
    this.actions = {}

    // Format the modules data passed in first
    // mutation and getters of nested modules need to be placed in this
    this.modules = new ModuleCollection(opts)
    console.log(this.modules)

    Store.installModules(this[],this.modules.root)
  }

  commit = (mutationName, value) = > { // There is a problem with this pointing, which is actually mounted on the instance
    this.mutations[mutationName].forEach(f= > f(value))
  }

  dispatch(actionName, value) {
    this.actions[actionName].forEach(f= > f(value))
  }

  get state() {
    return this.vm.state
  }
}
Store.installModules = function(store, path, curModule) {
  let getters = curModule._raw.getters || {}
  let mutations = curModule._raw.mutations || {}
  let actions = curModule._raw.actions || {}
  let state = curModule._state || {}

  // Mount the state of the child module to the parent module, and other modules directly to the root store
  if (path.length) {
    let parent = path.slice(0, -1).reduce((pre, cur) = > {
      return pre[cur]
    }, store.state)
    _Vue.set(parent, path[path.length - 1], state)
  }

  Object.keys(getters).forEach(getterName= > {
    Object.defineProperty(store.getters, getterName, {
      get: () = > {
        return getters[getterName](state)
      }
    })
  })

  Object.keys(mutations).forEach(mutationName= > {
    if(! (store.mutations && store.mutations[mutationName])) store.mutations[mutationName] = [] store.mutations[mutationName].push(value= > {
      mutations[mutationName].call(store, state, value)
    })
  })

  Object.keys(actions).forEach(actionName= > {
    if(! (store.actions && store.actions[actionName])) store.actions[actionName] = [] store.actions[actionName].push(value= > {
      actions[actionName].call(store, store, value)
    })
  })

  Object.keys(curModule._children || {}).forEach(module= > {
    Store.installModules(store, path.concat(module), curModule._children[module])})}// computed: mapState(['name'])
// equivalent to name(){return this.$store.state.name}
const mapState = list= > { // Because you end up calling it in computed
  let obj = {}
  list.forEach(stateName= > {
    obj[stateName] = () = > this.$store.state[stateName]
  })
  return obj
}

const mapGetters = list= > { // Because you end up calling it in computed
  let obj = {}
  list.forEach(getterName= > {
    obj[getterName] = () = > this.$store.getters[getterName]
  })
  return obj
}

const mapMutations = list= > {
  let obj = {}
  list.forEach(mutationName= > {
    obj[mutationName] = (value) = > {
      this.$store.commit(mutationName, value)
    }
  })
  return obj
}

const mapActions = list= > {
  let obj = {}
  list.forEach(actionName= > {
    obj[actionName] = (value) = > {
      this.$store.dispatch(actionName, value)
    }
  })
  return obj
}

export default {
  install,
  Store,
  mapState,
  mapGetters,
  mapMutations,
  mapActions
}
Copy the code

The silver version vuexthis.$stroe:

3. Use self-written vuex in app. vue:

<template>
  <div id="app">
    <button @click="$store.commit('add')">$store.commit('add'): {{$store.state.counter}}</button>
    <br>
    <button @click="$store.commit('updateName', new Date().toLocaleString())">$store.commit('updateName', Date): {{$store.getters.name}}</button>
    <br>
    <button @click="$store.dispatch('add')">async $store.dispatch('add'): {{$store.state.counter}}</button>
  </div>
</template>
<script>
...
Copy the code