Write a simple Vuex with Vue.observable

As a member of the Vue family bucket, the importance of Vuex is self-evident, both for state management and for encapsulating Controler.

But in some smaller projects, introducing Vuex for a few simple states or processing functions is like using anti-aircraft guns to kill mosquitoes.

At this point, you can simulate Vuex and write a simple Store to manage the status and update the data in real time.



1. Constructor

Simulate the structure of Vuex and create a Class

export default class Store {
  constructor({ states, actions, mutations }) {
    // state
    this.states = states || {};
    // Asynchronous function
    this.actions = actions || {};
    // Synchronization function
    this.mutations = mutations || {};
  // call mutations Synchronization function in
  commit = (fun, params) => {};
  // call actions Asynchronous function in
  dispatch = (fun, params) => {};
  // To update states The state of
  update = (key, value) => {};


Then instantiate a Store

import Store from './store';

import states from './states';
import actions from './actions';
import mutations from './mutations';

const store = new Store({

export default store;


Then hang onto the prototype of Vue and use it in the way of vue.$store. A high-imitation vuex shelf will be set up.

// stay main.js Introduction Store
import store from './store/index';
Vue.prototype.$store = store;



2. Implementing operation functions (commit, dispatch, update)

In Vuex, if you need to update the state in the state, you need to call the methods in mutations through commit

The mutations method has a default parameter state, so the commit method can be written as follows:

// towards mutations Fixed afferent parameters in state
commit = (fun, params) => {
  this.mutations[fun](this.states, params);


However, due to some historical problems, I am accustomed to using this.states to get state (this habit is not good), so I changed it to this way:

  commit = (fun, params) => {
    if (fun) {
      this.mutations[fun].call(this, params);
    } else {
      return false;

Similar actions and update s can refer to commit



3. Responsive Objects

The current store has a fatal problem: state updates do not immediately render to the view layer

At this point, the new observable() in Vue 2.6.0 comes in handy.


If an object is passed as an input parameter to Vue.observable(), after processing, the object can be updated in Vue in real time.

Its return value can be used directly in render and computed, and the corresponding update will be triggered when a change occurs.


So the Store constructor needs to be changed:

  constructor({ states, actions, mutations }) {
    // state
    this.states = Vue.observable(states || {});
    // Asynchronous function
    this.actions = Vue.observable(actions || {});
    // Synchronization function
    this.mutations = Vue.observable(mutations || {});



If the object obj is processed by observable(), it is assigned to the new object new_boj.

In Vue 2.x, directly modifying obj also triggers updates to new_box

But in Vue 3.x, because of the change of response mechanism, only modifying new_obj can trigger the update of view layer.

So when using observable(), it's better to always operate the new_obj after using observable().



4. Simple Use

Ultra-low-cost Vuex has been written and store has been attached to the prototype of Vue, so it can be used directly.

If a state name already exists in the state, it can be retrieved in the component by computer.

computed: {
    name() {
      return this.$store.states.name;

If you need to modify the status, you can use $store.update()

methods: {
    updateName(val) {
        this.$store.update('name', val);

Or use $store.commit() to call methods in mutations

methods: {
    commitName(val) {
        this.$store.commit('handleNameChange', val);

Great success

Tags: Javascript Vue

Posted on Tue, 10 Sep 2019 00:42:32 -0700 by RonDahl