Vuex from shallow to deep

1. Introduction to vuex

Vuex is a plug-in specially used to manage the state in the vue.js application. Its function is to put all the states in the application together and manage them centrally. What needs to be declared is that the state mentioned here refers to the attributes in the data in the vue component. People who know vue should understand what data is going on. If you don’t understand, it is recommended that you finish learning the basics of vue before looking at vuex.

2. Schematic diagram of the composition structure of vuex

The characteristic of vuex is to isolate the data separately to form a tree diagram. Isolation alone means that it has its own ecosystem. Input and output, where action is the input of data and state is the output of data. As shown in the figure below,
vuex
note: state can only be modified in mutaions, actions cannot directly modify state
mutations, that is, change, modify state data, and can only be synchronous, and there can be no asynchronous operations. What if you need to be asynchronous? Put the asynchronous operation in actions, get the data and process it synchronously through mutations. What vuex does is actually clarify the powers and subdivide the responsibilities. So it also says in its documentation that small systems can be used. There is little status data and no need to subdivide.

Through this diagram, we can easily see the components of vuex and the connection between vuex and components. In fact, this picture is a bit confusing. It doesn’t matter if you don’t understand it for the time being, as long as you have an intuitive understanding, you will understand if you use it more.

3. The core concept of vuex

3.1.1 Create store

import Vue from "vue";
import Vuex from "vuex";

import state from './state';
import actions from './actions';
import mutations from './mutations';
import getters from './getters';

Vue.use(Vuex);
export default new Vuex.Store({
    state,
    actions,
    mutations,
    getters
});

store is an instance of the new constructor of Vuex.Store. An object parameter can be passed in the constructor.
5 objects can be included in this parameter:

1.state – 存放状态

2.getters – state的计算属性

3.mutations – 更改状态的逻辑,同步操作

4.actions – 提交mutation,异步操作

5.mudules – 将store模块化

Note:
There are two points to remember about the store:
1. The state stored in the store is responsive. When the component reads the state from the store, if the state in the store changes, the corresponding component will also Get updated

2. You cannot directly change the state in the store. The only way to change the state in the store is to commit mutations. This allows us to easily track the changes of each state.

3.2 state

What's stored in state is simply a variable, which is the so-called state. When state is not used, we initialize directly in data,
but after we have state, we transfer the data from data to state. In addition, some states are private to the component, called the partial state of the component, and
we don’t need to put this part of the state in the store.

3.2.1 How to get the vuex status in the component

Since the state of vuex is responsive, the way to read the state from the store is to return a certain state in the calculated properties of the component.

  <Item v-for="(todo,index) in this.$store.state.todos" :key="index" :todo="todo" :index="index"></Item>

In this way, the state in the component is associated with the state in the store. Whenever store.state.todos changes, the calculated attributes will be re-calculated to update the DOM.

3.2.2 mapState
当一个组件获取多种状态的时候,则在计算属性中要写多个函数。为了方便,可以使用mapState辅助函数来帮我们生成计算属性。

<Item v-for="(todo,index) in todos" :key="index" :todo="todo" :index="index"></Item>
import { mapState } from "vuex";
computed: {
    ...mapState(["todos"]);
}

The above is assigned through the object of mapState, and it can also be assigned through the array of mapState.
This method is very simple, but the name of the state in the component is the same as the name mapped in the store

3.3 getters

Sometimes we need to derive some state from the state in the store, such as filtering and counting the list. At this time, getters can be used. Getters can be regarded as a calculated attribute of store, and its parameter is state.

const store = new Vuex.Store({
    state: {
        todos: [
            { id: 1, text: 'reading', done: true },
            { id: 2, text: 'playBastketball', done: false }
        ]
    },
    getters: {
        doneTodos: state => {
            return state.todos.filter(todo => todo.done);
        }
    }
});
3.3.1 Get the status in getters, method one
store.getters.doneTodos //  [{ id: 1, text: 'reading', done: true }]
//在组件中,则要写在计算属性中,
computed: {
    doneTodos() {
        return this.$store.getters.doneTodos;
    }
}
3.3.2 Use mapGetters to get the status in getters: method two
import { mapState, mapGetters } from 'vuex';
computed: {
    ...mapState(['increment']),
    ...mapGetters(['doneTodos'])
}	

3.4 mutations

Mutations are how to change the logic of the state in the state. The only way to change the state in Vuex is to submit a mutation, that is

store.commit(‘increment’)。

Put constants in separate files to facilitate collaborative development

import { 
	ADD_TODO, DELETETODO, 
	SELECT_ALL_TODOS,
	 CLEAR_ALL_COMPLETED 
} from './motatios-types';

More examples

export default {
    [ADD_TODO](state, { todo }) {
        state.todos.unshift(todo);
    },
    [DELETETODO](state, { index }) {
        state.todos.splice(index, 1);
    },
    [SELECT_ALL_TODOS](state, { check }) {
        state.todos.forEach(todo => todo.complete = check);
    },
    [CLEAR_ALL_COMPLETED](state) {
        state.todos = state.todos.filter(todo => !todo.complete);
    },
}

Note: mutation must be a synchronous function, not asynchronous, this is for the convenience of debugging

3.4.2 Submit mutations in the component

So where should the mutation be submitted? Because js is event-driven, the logic to change the state must be driven by events, so store.commit('increment') is executed in the component's methods.

Method 1: Submit in the methods of the component

methods: {
    increment(){
        this.$store.commit('increment');
    }
}

Method 2: Use mapMutaions

Use the mapMutations helper function to map the methods in the component to store.commit calls.

import { mapMutaions } from 'vuex';
export default {
    // ...
    methods: {
        ...mapMutaions([
            'increment' // 映射 this.increment() 为 this.$store.commit('increment')
        ]),
        ...mapMutaions([
            add: 'increment' // 映射 this.add() 为 this.$store.commit('increment')
        ])
    }
}
    // 因为mutation相当于一个method,所以在组件中,可以这样来使用
    < button @click="increment" > +</button>
3.5.3 Combination actions

Because the action is asynchronous, we need to know when the asynchronous function ends, and when it is executed, the result of an action will be used.
This can be achieved using promises. Return a promise in an action,
and then use the then() callback function to process the result returned by the action.

	actions: {
	    actionA({ commit }){
	        return new Promise((resolve, reject) => {
	            setTimeout(() => {
	                commit('someMutation');
	                resolve();
	            }, 1000);
	        })
	    }
	}

	// 这样就可以操作actionA返回的结果了
	store.dispatch('actionA').then(() => {
	    // dosomething ...
	});
	// 也可以在另一个action中使用actionA的结果
	actions: {
	    // ...
	    actionB({ dispatch, commit }) {
	        return dispatch('actionA').then(() => {
	            commit('someOtherMutation');
	        })
	    }
	}

4.mudules

Module is to split the store into small modules. The purpose of this is because when the store is very large, it is easy to manage if it is divided into modules.

4.1 Each module has its own state, getters, mutation, and action

const moduleA = {
    state: { ...},
    getters: { ...},
    mutations: { ....},
    actions: { ...}
}
const moduleB = {
    state: { ...},
    getters: { ...},
    mutations: { ....},
    actions: { ...}
}
const store = new Vuex.Store({
    modules: {
        a: moduleA,
        b: moduleB
    }
});
store.state.a // 获取moduleA的状态
store.state.b // 获取moduleB的状态

4.2 Status inside the module

For the mutation and getter inside the module, the first parameter accepted is the local state state of the module. By the way, the state of the root node is rootState.

const moduleA = {
    state: { count: 0 },
    getters: {
        doubleCount(state) {
            return state.count * 2;
        }
    },
    mutations: {
        increment(state) {
            state.count++;
        }
    },
    actions: { ...}
}

4.3 Dynamic registration of modules

在模块创建之后,可以使用store.registerModule方法来注册模块。
	
	store.registerModule('myModule', {
	    // ...
	});
依然可以通过store.state.myModule来获取模块的状态。

可以使用store.unregisterModule(moduleName)来动态的卸载模块,
但是这种方法对于静态模块是无效的(即在创建store时声明的模块)。

5 The structure of the project containing vuex

5.1 Rules to be followed

1. 应用层级的状态都应该集中在store中
2. 提交 mutation 是更改状态state的唯一方式,并且这个过程是同步的。

Guess you like

Origin blog.csdn.net/handsomezhanghui/article/details/105908419