The core concepts and functions of Vuex

Core concepts

Store has five core concepts, State, Getters, Mutations, Actions, and Modules. You have to know what they do.

State status

Each of our projects basically uses the same store instance, so the State is also shared. State is an object and the only data source. The data in the entire Store is managed and stored from the State. State is actually like option data in a Vue instance.

Basic case

Get State data in the component

Since State is reactive, it can be returned in conjunction with computed properties. Whenever state.count changes, the calculated property will be re-evaluated and an update of the associated DOM will be triggered.

<template>
    <div class="home">
        {<!-- -->{ count }}
    </div>
</template>

<script>
export default {
    computed: {
        count() {
            return this.$store.state.count
        }
    }
}
</script>

Get State data through mapState auxiliary function

When a component needs to obtain multiple State states, it will be somewhat repetitive and redundant to declare these states as computed properties. To solve this problem, we can use the mapState helper function to help us generate calculated properties to optimize your code.

<template>
    <div class="home">
        {<!-- -->{ count }}
    </div>
</template>

<script>
import { mapState } from 'vuex'

export default {
    computed: {
        ...mapState({
            count: (state) => state.count,
            name: (state) => state.name
        })
    }
}
</script>

Getters computed properties

Sometimes we need to derive some state from the state in the store. In this case, we need to use getters. In fact, getters are the same as computed properties. Because in some cases you feel that the state data is not in the format you want, you want to process it based on it and then use it. Of course, it will not affect the value of the original state.

Basic case

Define Getters and process them based on the original State

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

Vue.use(Vuex)

const store = new Vuex.Store({<!-- -->
    state: {<!-- -->
        name: 'xiaoming'
    },
    getters: {<!-- -->
        name(state) {<!-- -->
            return 'my name is ' + state.name
        }
    }
})

export default store

Get Getters data in the component

<template>
    <div class="home">
        {<!-- -->{ name }}
    </div>
</template>

<script>
export default {
    computed: {
        name() {
            return this.$store.getters.name
        }
    }
}
</script>

Get Getters data through mapGetters helper function

<template>
    <div class="home">
        {<!-- -->{ myName }}
    </div>
</template>

<script>
import { mapGetters } from 'vuex'

export default {
    computed: {
        // Map `this.name` to `this.$store.getters.name`
        ...mapGetters({
            myName: 'name'
        })
    }
}
</script>

Mutations synchronously modify State

The only way to change state in a Vuex store is to submit a mutation. Mutations are very similar to when Vue calls a child component, it passes data to the child component, and the child component notifies the parent component to modify the data through $emit. All use one-way data flow.

Basic case

Define mutations

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

Vue.use(Vuex)

const store = new Vuex.Store({<!-- -->
    state: {<!-- -->
        count: 0
    },
    mutations: {<!-- -->
        increment(state, payload) {<!-- -->
            state.count + = payload.num
        }
    }
})

export default store

Submit Payload

Mutations are called via $store.commit, and additional parameters can be passed in, namely the payload of the mutation.

<template>
    <div class="home">
        {<!-- -->{ $store.state.count }}
    </div>
</template>

<script>
export default {
    mounted() {
        setTimeout(() => {
            this.$store.commit('increment', { num: 10 })
        }, 1000)
    }
}
</script>

Get mutations function through mapMutations auxiliary function

You can use this.$store.commit('$mutationsName') in the component to commit mutations, or use the mapMutations helper function to map the methods in the component to $store.commit call.

<template>
    <div class="home">
        {<!-- -->{ $store.state.count }}
    </div>
</template>

<script>
import { mapMutations } from 'vuex'
export default {
    methods: {
        // Map `this.myIncrement()` to `this.$store.commit('increment')`
        ...mapMutations({
            myIncrement: 'increment'
        })
    },
    mounted() {
        setTimeout(() => {
            this.myIncrement({ num: 10 })
        }, 1000)
    }
}
</script>

Mutation needs to comply with Vue’s responsiveness rules

Since the state in the Vuex store is reactive, when we change the state, the Vue component that monitors the state will automatically update. This also means that mutations in Vuex also need to follow the same precautions as using Vue: for example, it is best to initialize all required states in your Store in advance.

Mutation must be a synchronous function

An important principle is to remember that mutations must be synchronous functions, and the internal logic must be synchronous. If it is asynchronous, the status cannot be tracked normally.

Actions asynchronously submit Mutations

Mixing asynchronous calls within mutations can make your program difficult to debug. For example, when you call two mutations that contain asynchronous callbacks to change state, how do you know when to call back and which one to call first? This is why we distinguish between these two concepts. In Vuex, mutations are all synchronous transactions and must modify the current state immediately.

Actions are similar to mutations. The difference between them is that Actions submit mutations instead of directly changing the state. Actions are asynchronous, and functions can contain any asynchronous operations.

Basic case

Define actions

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

Vue.use(Vuex)

const store = new Vuex.Store({<!-- -->
    state: {<!-- -->
        count: 0
    },
    mutations: {<!-- -->
        increment(state, payload) {<!-- -->
            state.count + = payload.num
        }
    },
    actions: {<!-- -->
        incrementAsync({<!-- --> commit }, payload) {<!-- -->
            setTimeout(() => {<!-- -->
                commit('increment', payload)
            }, 1000)
        }
    }
})

export default store

Distribute actions

Actions are triggered via the $store.dispatch method.

<template>
    <div class="home">
        {<!-- -->{ $store.state.count }}
    </div>
</template>

<script>
export default {
    mounted() {
        this.$store.dispatch('incrementAsync', {
            num: 10
        })
    }
}
</script>

Get the actions function through the mapActions helper function

<template>
    <div class="home">
        {<!-- -->{ $store.state.count }}
    </div>
</template>

<script>
import { mapActions } from 'vuex'

export default {
    methods: {
        // Map `this.myIncrementAsync()` to `this.$store.dispatch('incrementAsync')`
        ...mapActions({
            myIncrementAsync: 'incrementAsync'
        })
    },
    mounted() {
        this.myIncrementAsync({ num: 10 })
    }
}
</script>

Module module

Since the same state is used, all the states of the application will be concentrated into a relatively large object. When an application becomes very complex, store objects have the potential to become quite bloated.

In order to solve the above problems, Vuex allows us to split the store into modules. Each module has its own state, getters, mutations, actions, and modules.

Basic case

Define module

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

Vue.use(Vuex)

const moduleA = {<!-- -->
    namespaced: true,
    state: {<!-- -->
        count: 0,
        name: 'xiaoming'
    },
    getters: {<!-- -->
        name(state) {<!-- -->
            return 'my name is ' + state.name
        }
    },
    mutations: {<!-- -->
        increment(state, payload) {<!-- -->
            state.count + = payload.num
        }
    },
    actions: {<!-- -->
        incrementAsync({<!-- --> commit }, payload) {<!-- -->
            setTimeout(() => {<!-- -->
                commit('increment', payload)
            }, 1000)
        }
    }
}

const store = new Vuex.Store({<!-- -->
    modules: {<!-- -->
        a: moduleA
    }
})

export default store

Get State data through mapState auxiliary function

<template>
    <div class="home">
        {<!-- -->{ name }}
    </div>
</template>

<script>
import { mapState } from 'vuex'

export default {
    computed: {
        // Map `this.name` to `this.$store.state.a.name`
        ...mapState({
            name: (state) => state.a.name
        })
    }
}
</script>

Get Getters data through mapGetters helper function

<template>
    <div class="home">
        {<!-- -->{ myName }}
    </div>
</template>

<script>
import { mapGetters } from 'vuex'

export default {
    computed: {
        // Map `this.myName` to `this.$store.getters['a/name']`
        ...mapGetters({
            myName: 'a/name'
        })
    }
}
</script>

Get mutations function through mapMutations auxiliary function

<template>
    <div class="home">
        {<!-- -->{ $store.state.a.count }}
    </div>
</template>

<script>
import { mapMutations } from 'vuex'
export default {
    methods: {
        // Map `this.myIncrement()` to `this.$store.commit('a/increment')`
        ...mapMutations({
            myIncrement: 'a/increment'
        })
    },
    mounted() {
        setTimeout(() => {
            this.myIncrement({ num: 10 })
        }, 1000)
    }
}
</script>

Get the actions function through the mapActions helper function

<template>
    <div class="home">
        {<!-- -->{ $store.state.a.count }}
    </div>
</template>

<script>
import { mapActions } from 'vuex'

export default {
    methods: {
        // Map `this.myIncrementAsync()` to `this.$store.dispatch('a/incrementAsync')`
        ...mapActions({
            myIncrementAsync: 'a/incrementAsync'
        })
    },
    mounted() {
        this.myIncrementAsync({ num: 10 })
    }
}
</script>

Original link: vegetable garden front end