This is the 8th day of my participation in Gwen Challenge

Original TANGJIE Vue2 Vuex

The basic principle of VuEX & Simple handwriting vuex

To write a simple VUex, you must first know what vuex is, what the design goal is, and how it is used. Only in this way can we be stronger standing on the shoulders of giants.

1. Basic concepts of Vuex

Vuex is a repository that centrally manages and stores the state of all components of an application, with rules to ensure that state changes in predictable ways

1.1 Basic Concepts

  • State and data
  • Mutations, the word mutations means change, a function that changes state
  • Actions Asynchronous behavior
  • Store contains the container of the above concepts

1.2 Basic Usage

First picture:

In fact, it is very simple to use:

  1. Create a store directory under SRC to store the vuex code files (I like vuex modules under various routing components), and write state, mutations, actions, etc
import Vue from 'vue'
import Vuex from 'vuex'

import modelone from './modelone'
Vue.use(Vuex)
export default new Vuex.Store({
  state: {
  	name:'test',},mutations: { // Synchronize methods
  	setName(state,proload){
  		state.name = proload
  	}
  },
  actions: {
  	launchSetName(ctx,proload){ // Asynchronous method
  		// Change after 2 seconds
  		setTimeout(() = >{
  			ctx.commit('setName',proload)
  		},2000)}},modules: {
  	modelone
  }
})

Copy the code
  1. Use under components (basic use)
.// Get the value of state directly in store
this.$store.state.name
...
methods: {// Use mutation directly
  	changeStateName(){
  		this.$store.commit('setName'.'Xiao Ming has a crush on Xiao Hong')},// Use action directly
  	afterSecondsChangeName(){
  		this.$store.dispatch('launchSetName'.'Two seconds later Red ran away.')}}...Copy the code

See here compared to the above figure, is not a sudden clear up, the original use is so simple ~

  1. Component under use (usevuexGive themapXXXTo use)
.computed: {// Map the property value of state. mapState({name:state= > state.name
  	})
 },
methods: {// use mutation in map mode. mapMutations({changeMapStateName: 'setName'
  	}),
  	// Map uses action. mapActions({launchSetName:'launchSetName'})}...Copy the code

1.3 Thinking about vuEX usage scenarios

While vuEX is comfortable with state sharing across hierarchies, maintenance, code migration, and more can be cumbersome. Personally, it is not appropriate to store too many state attributes in Vuex. For global attributes of routing components, provide/ Inject is more silkier than Vuex.

However, in many development practices, the data of back-end asynchronous request are included in VUEX state management, and the logic of adding, deleting, modifying and checking data is encapsulated in Action. In this way, the front-end logic code can be layered to a certain extent, so that the code in the component pays more attention to the logic of the view layer such as page interaction and data rendering. I have reservations about vuex managing vUE for asynchronous requests, persistence of state data, etc. Back-end API management can be managed by a separate API file. Keep-alive is a better choice for persistence of background data

Up to now, I think the biggest role of VUEX is in SSR. (Personal opinion)

2. Develop a simple Vuex

Through the above understanding of the basic concept of VUEX and the use of VUEX, start from the perspective of use, a simple VUEX development. So that we can have a deeper and thorough understanding of VUEX

2.1 The first step is to create an install method

In this install method, to implement the Store instance and mount it to Vue prototype, Use (vuex.store) occurs before or after new Store(). In order to ensure that an instance of Store can be obtained, it is generally handled as follows

const install = ( Vue ) = >{
  vueComponent = Vue;
  Vue.mixin({
    beforeCreate(){
      if(this.$options.store){
          Vue.prototype.$store = this.$options.store
      }
    }
  })
}
Copy the code

Some of you might have questions here, right? This.$options.store = Vuex; this.$options.store = Vuex

.new Vue({
  router,
  store,
  render: h= > h(App)
}).$mount('#app')...Copy the code

From the above code we can clearly see that the instantiated Store is directly new Vue(…). Vue. Mixin is mixed into all Vue instances, but only Store instances are initialized. Vue.

2.2 Building the Store class

From a Vuex usage point of view, building a Store class is easy

class Store{
  constructor( options ){
    // Create the Store state property, because state is reactive and therefore reactive
    this.state = options.state
    vueComponent.observable(this.state);
    // Create the Store actions property
    this.actions = options.actions
    // Open the mutations attribute of the Store
    this.mutations = options.mutations
    / / bind this
    this.commit.bind(this);
    this.dispatch.bind(this);
  }
  commit(){}
  dispatch(){}}Copy the code

2.3 establishcommitMethods the function

According to mutations,commit takes two parameters, one is the mutation attribute name under Store and the other is the payload parameter, and then triggers the function on mutations. There is the following code for this

.commit(type,payload){
  if( this.mutations[type] ){
    this.mutations[type](payload)
  }
}
...
Copy the code

Actions is similar to mutation!

2.4 Complete Code

let vueComponent;

class Store {
  constructor( options ){
    
    console.log( this === Store.constructor,this ,'this')
    
    this.mutations = options.mutations;
    this.actions = options.actions;
    this.state = options.state;
    // Bind this, the context always points to the store instance
    this.commit.bind( this );
    this.dispatch.bind( this );
    // make state reactive
    vueComponent.observable(this.state);
  }
  
  commit(type,payload){
    const entry = this.mutations[type];
    if(entry){
      entry(this.state,payload)
    }
  }
  
  dispatch(type,payload){
    const entry = this.actions[type];
    if(entry){
        entry(this,payload)
    }
  }
}

const install = ( Vue ) = >{
  vueComponent = Vue;
  Vue.mixin({
    beforeCreate(){
      if(this.$options.store){
          // Mount store to the vue prototype
          // This is because the Vue plugin is used in Vue. Use
          Use tends to occur faster than Store instantiation
          // Therefore, the lifecycle is needed to ensure that the Store instance is retrieved
          Vue.prototype.$store = this.$options.store
      }
    }
  })
}

export default{
  Store,
  install
};
Copy the code