With some simple flow charts and text instructions, this article presents a simpler way to understand the principles of Vuex that deviates from the source code. Let us understand the operation mechanism behind Vuex when using it, so that we can better use and debug and solve problems.

1. What is Vuex?

Vuex is a state management mode developed specifically for vue.js applications. It uses centralized storage to manage the state of all components of an application and rules to ensure that the state changes in a predictable way. In simple terms, Vuex provides a convenient, accurate and predictable state management method for the sharing and modification of data between components in a single page application with multiple components interacting with each other.

2. Vuex core concepts

Before looking at the Vuex source code, there are some core Vuex concepts that need to be briefly introduced to help you understand the source code better.

  • State: State, which is the object managed by Vuex core;
  • Getters: derived state, secondary wrapping of state (e.g., default backend timestamp to date format). Methods in Getters are available to all components;
  • Mutations: All state changes are made by submitting mutation and mutation-like events, defining the event type and the callback function, which is where the state changes are made. The changes must be simultaneous, ensuring that the changes can be traced.
  • Actions: the state is also modified, but the only difference with Mutations is that the status is changed asynchronously, which is essentially Mutation in the callback submission.
  • Modules: In order to solve the problem of huge state tree and bloated store, the concept of Module is proposed to divide store into each module, and each module is a small store.

Vex2.0 source code structure

This article introduces the source code part of VEX2.0, first look at the whole source code composition, as shown below:

The Vuex source section consists of five parts:

  • Install: install part of the source code;
  • Store: source code core, this article focuses on the content;
  • API: The source code provides some internal and external apis;
  • Auxiliary functions: grammar sugar, which makes writing easier when using Vuex;
  • Plugin: Provides some default plugins, we can also customize the extension plugin writing.

4. Core source code analysis

4.1, install

The core purpose of installing part of the source code is to inject a Store property into the Vue.

The overall process is as follows:

Core injection source code:

Function vuexInit () {const options = this.$options // store inject if (options.store) {this.$store = options.store} else  if (options.parent && options.parent.$store) { this.$store = options.parent.$store } }Copy the code

4.2, store

Store is the core content of the whole Vuex, other parts of the source code are to support the Store, in the Store to complete the registration of all components shared data (state), call and modify methods. Let’s start with a flow diagram of the store constructor:

The Store is like an ecosystem in which every component of the entire application is registered, achieving predictable management of state. Environmental testing is required before registration, which is like the ticket, or passport, to the registration of this ecological environment; After the registration criteria are met, some internal properties and methods are initialized, which is like setting up the “stage” for the registration work, and the rest of the registration work is done on this stage.

2, installModule

The source code of the installation module is mainly to complete the registration of state, mutations, Actions and getters of the module. First, take a general look at the source code composition:

At the initial stage of module installation, some internal API registration was carried out, followed by state update, with the update logic as follows:

Hot update: When you unregister a module, the logic is to install an empty module to update it, and the update is a hot update. Hot update status changes are handled separately.

After obtaining the state of the parent node, perform a COMMIT based on the state of the parent node to complete the module’s state update to the State tree. The source code is as follows:

if (! isRoot && ! hot) { const parentState = getNestedState(rootState, path.slice(0, -1)) const moduleName = path[path.length - 1] store._withCommit(() => { Vue.set(parentState, moduleName, module.state) }) }Copy the code

Next is a store localization, which completes the localization of Dispatch, COMMIT, getters, and state. The goal of localization is to better manipulate data methods.

The logic of mutations registration is almost similar to the logic of actions registration, which is as follows:

There are two properties in the store environment: _mutations and _Actions are used to store the mutations and actions defined by the module respectively, search the corresponding internal attribute object according to the type of the current module, and package the corresponding callback function of the module into the corresponding attribute object, and then complete the registration. The difference lies in the processing of the wrapper callback function. The mutation directly wraps the callback function, and the action handles the result of the callback function as a Promise object, and then wraps it.

The registration logic of Getters is as follows:

Getters are designed to get derived state, so naming definitions are not allowed to repeat, first by module type, based on the internal property _wrappedGetters, which stores the registered getters for the entire application. The next step is to register the module’s getters by type. Finally, a submodule recursively calls the method.

InstallModule has just finished registering modules, and there is still some code to deal with before we can use these states.

4.2.2, resetStoreVM

This method is the final use of state and getters so that the user can invoke these states. The source logic is as follows:

The core is an internal variable called store._vm, which essentially passes the registered state and getters as a new data source instantiating a Vue object to Store. _VM, and removes the old store. _VM. At the same time, define store.getters. XXX =store._vm[XXX] to complete the correct posture for using getters. State is used by an API provided within the store. Calling this API returns store._vm.data.? http://state.xxx, you can access the module’s state after updating store._VM.

Mutations and Actions are implemented using two important apis provided internally through the Store, and the API section is introduced next.

5, API

5.1 the commit and dispatch

The two apis are used for mutations and Actions, respectively. The source logic is as follows:

The logic of COMMIT is: get the corresponding mutations based on the parameters from the internal property object registered above, and submit the packaged callback function through _withCommit. Meanwhile, use the internal API SUBSCRIBE to track and subscribe for state modification. Dispatch takes the registered actions by parameter, and promise.all performs a callback, in which commit is performed.

5.2 _withCommit

_withCommit (fn) {
    const committing = this._committing
    this._committing = true
    fn()
    this._committing = committing
 }
Copy the code

This internal API is the core source code for every commit state change, and the logic is simple: every time you do a state change, make sure the internal property _research is true (right), and the default initialization value of this property is false. So if _research is not true (right) when tracking state changes, you think this change is incorrect. There are also some internal apis like registerModule, unregisterModule, hotUpdate, Watch, subscribe, etc., which will not be described in detail here.

6. Auxiliary functions

In addition to the API provided above, Vuex also provides helper functions, a set of syntaxes that operate on various store properties, to make it easier to use Vuex. Specifically, it is divided into four auxiliary functions: mapState, mapMutations, mapActions and mapGetters. To explain more clearly the packaging form of grammar sugar, let’s take a look at how to use it:

Computed: mapState({// Arrow function makes code more concise count: State => state.count, // Pass string argument 'count' equal to 'state => state.count' countAlias: CountPlusLocalState (state) {return state.count + this.localcount}})Copy the code

For example, the above code is to use the method, from the amount of code is indeed simplified a lot, such a packaging process is important to translate this syntax sugar into computer recognizable JS code, so in the process of source code packaging mapState actually do a very important thing: State is injected into the computed property of the Vue instance, and the full execution function can be restored by functional deconstruction packaging of syntactic sugar of different formats.

Similarly, mapMutations, mapActions and mapGetters can be explained: MapMutations and mapActions inject commit and dispatch into methods of the Vue instance, respectively, and mapActions inject getters into computed in the Vue instance. The rest are some of the syntax sugar writing to function form, for these types of syntax sugar encapsulation in the source code are much the same.

7, the plugin

Vex2.0 provides two plugins: devtool and Logger. Log plugins that access developer tools and output state changes; There is no need to explain the plugin logic from the source code point of view, but we may need to understand and master some internal APIS and attributes provided by the plugin during the development process, such as SUBSCRIBE internal API, such as travel-to-state, mutation hook function, etc. In this way, we can develop plug-ins according to our own needs.

8, summary

This paper introduces the source code of Vuex2.0 core, the overall amount of source code is not large, through some simple process and introduce the source code operation mechanism, so that we basically understand the principle of Vuex on the basis of the source code.

This article introduces the core part of the source code, the source code also has some auxiliary functions and internal API worth careful consideration and taste, or I hope you have the opportunity to read the complete source code, so as to more complete understanding of Vuex, but also easier to help you debug; Secondly, through reading the source code, the overall understanding of its design concept and coding style, to help you in the future on the road to technical high engineering practice learning.