Vuex

Status management (store)

If you are not developing a large SPA, using Vuex may be too cumbersome. If you have multiple non-parent components sharing one or more states (data) at the same time, then Vuex can be said to be “once it’s done, it’s done”.

Preface

Not long after I joined the company, the leader asked me to write a document about Vuex. I wondered why I had to write one when there was a document on the official website. Later, I thought that maybe the leader would give me some tasks to review it again. Can we say the truth, I have not written a document 🙄, do not know how to write, so I according to the previous note format to write. The following is only Vuex more core applications, other advanced use of small partners please refer to the official documents.

The installation

npm i vuex –s

//	store/index.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store(options)
Copy the code
// main.js
import Vue from 'vue'
import App from './App.vue'
import store from './store'

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

Use (Vuex) to install Vuex in index.js and refer to it in main.js

The simplest store

The core of Vuex is the Store, which contains most of the states in the app.

After installation, create a simple Store that requires only one state and mutations:

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
    state: {num:0
    },
    mutations: {addNum(state){
            state.num++
        }
    }
})
Copy the code

This.$store.xxx can be used to access or modify the state (or data) in the vue file.

Vuex.store () Configures the object

The configuration object has four attributes: State, mutations, getters, and Actions

state

A data object similar to a Vue instance uses state to store the state shared by the application. States in state are reactive

// Store /index.js state object
state: {pageTitle:'use Vuex'.pageConut:1.pageDescribe:'This page introduces the use of Vuex.'
    }
Copy the code
<template>
	<div>
        <h3>{{ title }}</h3>
    </div>
</template>
<script>
export default{
    data(){
        return:{}
    },
    computed: {title:function(){
            return this.$store.state.pageTitle
        }
    }
}
</script>
// Display content: use Vuex
Copy the code
mapState

This.$store.state. XXX can be used to make a value in state into a computed object, but if there are too many states in state and multiple values have to be taken, using the same format will make a computed object too long. So Vuex provides an easier way: the mapState() helper function 👇

<template>
	<div>
        <h3>{{ pageTitle }}</h3>
        <p>{{ pageConut }}</p>
        <p>{{ pageDescribe }}</p>
    </div>
</template>
<script>
/ / into the mapState
import { mapState } from 'vuex'
    
export default{
    data(){
        return:{}
    },
    computed: {... mapState(['pageTitle'.'pageConut'.'pageDescribe'])}}</script>
// Display content:
// use Vuex
// 	1
// This page introduces the use of Vuex.
Copy the code

. MapState ([]) maps the content of [], that is, the state, to computed, which is equivalent to using this.$store.state.xxx for each state. If you want an alias, you can use the form of an object:

<template>
	<div>
        <h3>{{ title }}</h3>
        <p>{{ conutNum }}</p>
        <p>{{ desc }}</p>
    </div>
</template>
<script>
    import { mapState } from 'vuex'
	export default{
        computed: {... mapState({title:'pageTitle'.countNum:'pageCount'.desc:'pageDescribe'}}})</script>
// Display the same content as above
Copy the code

mutations

The only way to change the state in store of Vuex is to submit mutation, which is similar to the methods object of Vue instance. The first parameter of each function under Mutations must be state, and the second parameter is the new value passed in. This is accessed and modified within the function via state.xxx. Also, mutations must be synchronized 👇

export default new Vuex.Store({
    mutations: {changeCount(state){
            state.pageCount++
        }
    }
})
Copy the code
<template>
	<div>
        <h3>{{ title }}</h3>
        <p>{{ conutNum }}</p>
        <button @click="add">Click on the add</button>
        <p>{{ desc }}</p>
    </div>
</template>
<script>
    import { mapState } from 'vuex'
	export default{
        methods: {addNum(){
                this.$store.commit('changeCount')}}}</script>
// Each time you click the button, the 'changeCount' method will be submitted, and the state.pagecount method will +1,
// Since it is reactive, the countNum of the page will also change
Copy the code
mapMutations

If you need multiple methods to modify multiple states, it will be redundant to write them all to methods, so Vuex also provides an auxiliary function: mapMutations():

export default new Vuex.Store({
    mutations: {changeCount(state){
            state.pageCount++
        },
        changeTitle(state,val){
            state.pageTitle = val
        },
        changeDesc(state,val){
            state.pageDescribe = val
        }
    }
})
Copy the code
<template>
	<div>
        <h3>{{ title }}</h3>
        <input v-model='newTitle' @keyup.enter='changeTitle(newTitle)' type='text' placeholder='please input new title'>
        <p>{{ conutNum }}</p>
        <button @click="changeCount">click to increase</button>
        <p>{{ desc }}</p>
        <input v-model='newDesc' @keyup.enter='changeDesc(newDesc)' type='text' placeholder='please input new describe'>
    </div>
</template>
<script>
    import { mapState , mapMutations } from 'vuex'
	export default{
        data(){
            return {
          		newTitle:' '.newDesc:' '}},methods: {... mapMutations(['changeCount'.'changeTitle'.'changeDesc']),}}</script>// Click the button countNum to add // Enter the new content in the input box, and press enter to change the title and descCopy the code

. MapMutations ([]) maps the methods of mutations in store to methods, which can be used directly when label events are added, can be called through this.xxx(), or can be alias through the form of the object

getters

Derived states or new states based on the states in state. Each function under getters takes state as its first argument to access the state, and can also take other getters as its second argument. Getters are also similar to computed objects and, like computed, are cached based on dependencies and are not recalculated on the second call as long as the original state has not changed. Note: The result is not cached when getters is called and the new state is returned based on the argument.

export default new Vuex.Store({
    state: {listArr:[
            {
                name:'jack'.age:18
            },
            {
                name:'john'.age:19
            },
            {
                name:'ray'.age:18
            },
            {
                name:'monica'.age:20}},getters: [screenList(state){
        	return state.listArr.filter((item) = >{
    			return item.age === 18}})})Copy the code
<template>
	<p>{{ screenItem }}</p>
</template>
<script>
    import { mapState , mapMutations } from 'vuex'
	export default{
        computed: {screenItem(){
                return this.$store.getters.screenList
            }
        }
    }
</script>
// After running, the page displays two objects with age === 18 in the listArr array in state
Copy the code

Getters also has a helper function called mapGetters, which maps functions in getters to computed and can be aliased as objects

Getters are accessed by methods
export default new Vuex.Store({
    getters: {screenList: (state) = > (num) = > {
            return state.listArr.find((item) = > item.age === num)
        }
    }
})
Copy the code
<template> <! --<p>{{ screenItem(20) }}</p> -->
	<p>{{ screenList(20) }}</p>
</template>
<script>
    import { mapState , mapMutations , mapGetters }
	export default{
        computed{
        	//screenItem(){
            // return this.$store.screenList
            / /}. mapGetters(['screenList'])}}</script>
// A function that accesses getters through a method returns an object that has been filtered by the parameters. In this case, getters are not cached.
Copy the code

actions

They’re kind of like mutations, except that what actions are delivering are mutations, and they involve asynchronous operations. The actoins method accepts context as the same argument as the Store instance, but cannot pass store as a parameter. See the official documentation for details. The actions function is dispatched (called) within the component via this.$store.dispatch(‘ XXX ‘).

export default{
    actions: {actionA(context){
            setTimeout(() = > {
            	context.commit('changeCount')},2000)}}}Copy the code
<template>
	<button @click='add'></button>
</template>
<script>
	export default{
        methods: {add(){
                this.$store.dispatch('actionA')}}}</script>
// Click the button and after 2 seconds countNum will +1
Copy the code

Above is a simple asynchronous operation. If there are complex operations, since this.$store.dispatch can handle the promise returned by the actions and the Dispatch also returns a Promise, the actions can be handled internally with a Promise

export default new Vuex.Store({
    actions: {actionB(context){
            return new Promise((resolve, reject) = > {
                setTimeout(() = > {
                   context.getters.screenList
                   resolve()
                },2000)})}})Copy the code
<template>
	<button @click='show'>please click</button>
</template>
<script>
	export default{
        methods: {async show(){
                try{
                    let res = await this.$store.dispatch('actionB')
                    if(res) console.log(res)
                }catch(err){
                    console.log(err)
                }
            }
        }
    }
</script>
// Click the button, and after 2 seconds the console displays the value returned by screenList
Copy the code

Actions also have helper functions: mapActions(), which map internal functions to methods, can be called from this.xxx(), and can also be aliases from objects

Actions are not very useful, and although they can handle AXIOS requests, the usual requests are handled inside the component

modules

When the application is very complex, all the shared states are concentrated in the Store, which will become very bloated. So the whole object can be divided into small modules, each module has its own state, mutations, getters and actions, without interfering with each other. 👉 Vuex modules

Modules is technically a member of the vuex.store (Options) configuration object, so its configuration object has five properties.

The last

Thank you guys, each big guy read this document (should be a document 😁), as a nugget small white, the first time to write more flaws, also hope you nugget predecessors many guidance. If there is any wrong place, please put forward, I will timely change