“This is the 18th day of my participation in the Gwen Challenge in November. See details: The Last Gwen Challenge in 2021.”

Vuex is a state manager, and readers will first read the author’s implementation of the ultra mini state management tool, a total of 30 lines of code. Get a taste of what vuex is all about with this mini.

Code using ES6 class grammar, all objects, the attributes and methods of an object encapsulated in a class, external do not need to care about its specific implementation details, only need to call the object out of the interface, even if the underlying implementation has changed, still will not affect your use of it. Using the class approach, the code structure is more cohesive, rather than the prototype-based approach, the code is more scattered. The dynamic prototype of JS also brings hidden trouble to the stability of the program. Well, it’s a matter of opinion.

class Vuex {
	_actions = Object.create(null);
	constructor() {
		this.state = Object.create(null);
	}

	createStore(options) {
		const { initialState, actions = [] } = options;
		this.immutableState(initialState);
		actions.forEach(({ type, handler }) = > {
			if (!this._actions[type]) {
				this._actions[type] = [];
			}
			this._actions[type].push(handler);
		});
		return this;
	}
	immutableState(nextState) {
		constprevState = { ... this.state };constnewState = { ... prevState, ... nextState };this.state = newState;
	}

	dispatch({ type, payload }) {
		const actions = this._actions[type];
		let obj = actions.reduce((stateObj, handler) = > {
			return{... stateObj, ... handler(this.state, payload) };
		}, Object.create(null));
		this.immutableState(obj); }}const store = new Vuex().createStore({
	initialState: { uName: "kio" },
	actions: [{type: "changeName".handler: (prevState, payload) = > {return { uName: payload.val+prevState.uName }; }},]});console.log(store.state.uName, "1");
store.dispatch({
	type: "changeName".payload: { val: "cute"}});console.log(store.state.uName, "- 2");

Copy the code

Let’s analyze it:

  • _Actions. First of all, Vuex objects have an internal object property, _Actions, which stores our handling of operational states. This is a state management convention, and any state that needs to be changed needs to be changed by triggering an action via Dispatch.
  • State, this property is available for external access to the state.
  • Each state change triggers a change in the store state property. Immutable means that an object cannot be changed. Any change is a new state, so the extension operator is used to copy an object.
  • The createStore method initializes the state tree once and installs the action into the store’s _actions property.
  • Each time an operation is dispatched, the new state is returned by looking up the corresponding handler by Type, changing the store’s state tree by calling the immutableState method.
  • The following code is to use the example, the reader can copy the code to the console, actually feel, I have tested, there is a bug call me in the middle of the night.

The author can optimize it on this basis:

  • For example, by rewriting the access descriptor for state, direct operations on state objects are prohibited, but only by the conventional dispatch operation.
  • Such as adding asynchronous operation capabilities.
  • Add modularity management, for example, to implement a modular collection object.
  • For example, add a namespace cache and look up processors by path, just like dom path looks up.
  • For example, through proxy caching, closure caching optimizes lookup performance.
  • For example, write installation methods that inject the state manager into the prototype of the vue root instance.
  • Such as recording the history of every change, time travel and other advanced features.

Finally, let’s examine the following code:

function resetStoreVM (store, state, hot) {
  store.getters = {}
  store._makeLocalGettersCache = Object.create(null)
  const wrappedGetters = store._wrappedGetters
  const computed = {}
  forEachValue(wrappedGetters, (fn, key) = > {
    computed[key] = partial(fn, store)
    Object.defineProperty(store.getters, key, {
      get: () = > store._vm[key],
      enumerable: true
    })
  })
  store._vm = new Vue({
    data: {
      $$state: state
    },
    computed
  })
}
Copy the code
  • To reset the STORE VM instance, you need to destroy the old Vue instance.
  • Also clear the local value function cache.
  • Iterate through the partial function to ensure that the VM instance is updated.
  • By defining access descriptors, the state lookup of the object store is transferred to the Vue instance, thus transferring the real state management to the mediation Vue instance, so vuex is strongly bound to Vue.
  • The redux(mostly used with React) state management tool is not strongly bound to any library.

To sum up, the state management tool was developed to solve the problem of confusing state management, and it is also the implementation of the observer mode, when the state changes, the corresponding processor will be triggered. It provides friendly support for global communication. In addition to addressing these pain points, it also comes with advanced features such as time travel.