Learn Vuex 4.0 state management (Vite)

Posted by zalath on Fri, 11 Feb 2022 20:54:37 +0100

Contents of this article

  1. Briefly introduce vite and build vite project.
  2. Installing vuex
  3. Introduction to Vuex Basics
  4. Using Vuex
  5. Plug in introduction

    1. Briefly introduce vite and build vite project

    1.1 what is vite?

    Vite is a new front-end construction tool, which can significantly improve the front-end development experience. It consists of two main parts:

  6. A development server that provides rich built-in functions based on native ES modules, such as amazing module hot update (HMR).
  7. A set of build instructions that use Rollup to package your code, and it is pre configured to output highly optimized static resources for production environments.

Vite aims to provide out of the box configuration. At the same time, its plug-in API and JavaScript API bring a high degree of scalability and complete type support.
Vite will use esbuild to pre build dependencies. Esbuild is written in Go and is 10-100 times faster than the packer pre build dependency written in JavaScript.

1.2 initialize vite

npm init vite@latest

1.3 create the first vite project

Vuex is designed for Vue JS application development state management mode + library. It uses centralized storage to manage the state of all components of the application, and uses corresponding rules to ensure that the state changes in a predictable way.

2. Install vuex

npm install vuex@next --save

3. Introduction to vuex Basics

3.1 vuex

The core of every vuex application is the store. "Store" is basically a container, which contains most of the states in your application. Vuex differs from simple global objects in the following two points:

Vuex's state storage is responsive. When Vue components read the state from the store, if the state in the store changes, the corresponding components will be updated efficiently accordingly.

You can't directly change the state in the store. The only way to change the state in the store is to explicitly commit the mutation. This makes it easy for us to track the changes of each state, so that we can implement some tools to help us better understand our application.

It mainly includes five parts: State, Getters, variables, Actions and Module.

3.1.1 State concept

Vuex uses a single state tree -- yes, all application level states are contained in one object. At this point, it exists as a "unique data source (SSOT)". This also means that each application will contain only one store instance. The single state tree enables us to directly locate any specific state segment, and easily obtain a snapshot of the current application state during debugging.

3.1.2 module

Due to the use of a single state tree, all the states of the application will be concentrated in a relatively large object. When the application becomes very complex, the store object may become quite bloated.
To solve the above problems, Vuex allows us to divide the store into modules. Each module has its own state, mutation, action, getter, and even nested sub modules - split in the same way from top to bottom: thus, it is divided into two state management modules. (test and test1 modules).

//store/test.js
export const test = {
    namespaced: true,
    state: {
        name: 'Tell me Zhan to hide',
        gender: 'male',
        profession: 'Front end development',
        age: 10
    }
}

//store/test1.js
export const test1 = {
    namespaced: true,
    state: {
        name: 'February',
        sport: 'Running, code and music',
        publics:'Tell me Zhan to hide',
        amount:100
    },
}

3.1.3 namespace

By default, the actions and changes inside the module are still registered in the global namespace -- this enables multiple modules to respond to the same action or change. getter is also registered in the global namespace by default, but at present, this is not for functional purposes (just to maintain the status quo to avoid incompatible changes). You must be careful not to define two identical getters in different modules without namespaces, resulting in errors.
If you want your module to have higher encapsulation and reusability, you can make it a module with namespace by adding named: true.

3.1.4 Getters definition

Sometimes we need to derive some states from the state in the store, such as:

//store/test.js
export const test = {
    namespaced: true,
    state: {
        name: 'Tell me Zhan to hide',
        gender: 'male',
        profession: 'Front end development',
        age: 10
    },
    //Some states derived from state can be extracted into functions for easy calling
    getters: {
        getUserInfo: state => {
            return state.name + 'My occupation is' + state.profession
        },
        getUserSex: state => {
            return state.name + 'What's your gender' + state.gender
        }
    },
}

//store/test1.js
export const test1 = {
    namespaced: true,
    state: {
        name: 'February',
        sport: 'Running, code and music',
        publics:'Tell me Zhan to hide',
        amount:100
    },
    getters: {
        getSport: state => {
            return state.name + 'Favorite run is' + state.sport
        },
        getPublics: state => {
            return state.name + 'The official account is' + state.publics
        }
    },
}

3.1.5. Variations definition

The only way to change the state in Vuex's store is to submit the mutation. The mutation in Vuex is very similar to events: each mutation has a string event type and a callback function (handler). This callback function is where we actually change the state, and it will accept state as the first parameter:

//store/test.js
export const test = {
    namespaced: true,
    state: {
        name: 'Tell me Zhan to hide',
        gender: 'male',
        profession: 'Front end development',
        age: 10
    },
    //Some states derived from state can be extracted into functions for easy calling
    getters: {
        getUserInfo: state => {
            return state.name + 'My occupation is' + state.profession
        },
        getUserSex: state => {
            return state.name + 'What's your gender' + state.gender
        }
    },
    mutations: {
        testMutation1(state) {
            // Change status
            state.age++;
        },
        // The second parameter is the load
        testMutation2(state, payload) {
            state.age += payload.content;
        }
    },
}

//store/test1.js
export const test1 = {
    namespaced: true,
    state: {
        name: 'February',
        sport: 'Running, code and music',
        publics:'Tell me Zhan to hide',
        amount:100
    },
    getters: {
        getSport: state => {
            return state.name + 'Like to run' + state.sport
        },
        getPublics: state => {
            return state.name + 'The official account is' + state.publics
        }
    },
    mutations: {
        test1Mutation1(state) {
            state.amount++;
        },
        // The second parameter is the load
        test1Mutation2(state, payload) {
            state.amount += payload.amount;
        }
    },
}

3.1.6.actions definition

Action is similar to mutation in that:
The Action submits the mutation instead of directly changing the state.
An Action can contain any asynchronous Action.

//store/test.js
export const test = {
    namespaced: true,
    state: {
        name: 'Tell me Zhan to hide',
        gender: 'male',
        profession: 'Front end development',
        age: 10
    },
    //Some states derived from state can be extracted into functions for easy calling
    getters: {
        getUserInfo: state => {
            return state.name + 'My occupation is' + state.profession
        },
        getUserSex: state => {
            return state.name + 'What's your gender' + state.gender
        }
    },
    mutations: {
        testMutation1(state) {
            // Change status
            state.age++;
        },
        // The second parameter is the load
        testMutation2(state, payload) {
            state.age += payload.content;
        }
    },
    actions: {
        testAction1(context) {
            context.commit('testMutation1');
        },
        //The code is simplified by parameter deconstruction, and testAction1 is simplified to testAction2
        testAction2({ commit }, payload) {
            commit({
                type: 'testMutation2',
                content: payload.content
            });
        }
    }
}

//store/test1.js
export const test1 = {
    namespaced: true,
    state: {
        name: 'February',
        sport: 'Running, code and music',
        publics:'Tell me Zhan to hide',
        amount:100
    },
    getters: {
        getSport: state => {
            return state.name + 'Favorite run is' + state.sport
        },
        getPublics: state => {
            return state.name + 'The official account is' + state.publics
        }
    },
    mutations: {
        test1Mutation1(state) {
            state.amount++;
        },
        // The second parameter is the load
        test1Mutation2(state, payload) {
            state.amount += payload.amount;
        }
    },
    actions: {
        test1Action1(context) {
            context.commit('test1Mutation1');
        },
        test1Action2({ commit }, payload) {
            commit({
                type: 'test1Mutation1',
                content: payload.content
            });
        }
    }
}

The store warehouse has been maintained and our state is used in the component.

4. Status use

4.1 introduction

//store/index.js content

import { createStore } from "vuex";
import { test } from "./modules/test";
import { test1 } from "./modules/test1";

export const store = createStore({
  // Vuex allows the store to be divided into small modules, and each module has its own state, mutation, action and getter;
  // Status of accessing test: store state. test
  modules: {
    test, //store module 1
    test1 //store module 2
  }
});

main.js usage

//main.js
import { createApp } from 'vue'
import App from './App.vue'
import { store } from './store'
let app = createApp(App)
app.use(store).mount('#app')

4.2 use status in components

4.2.1 using state

Status in test

//Status in test
<h3>1.test modular state State of</h3>
<h5>{{userName}}</h5>
<h5>{{userInfo}}</h5>

<script setup>
import { computed } from 'vue'
import { useStore } from 'vuex'
const store = useStore()
/* ------------test Module status-----------------*/
//Get the status of test1 module
const userName = computed(() => store.state.test.name)
const userInfo = computed(
  () => store.state.test.name + 'My occupation is:' + store.state.test.profession
)
</script>

Status in test1

//Status in test1
<h3>1.test1 modular state State of</h3>
<h5>{{sport}}</h5>
<h5>Official account:{{publics}}</h5>

//Get the status of test2 module
const publics = computed(() => store.state.test1.publics)
const sport = computed(
  () => store.state.test1.name + 'Favorite sports:' + store.state.test1.sport
)

4.2.2 using getters

Status of test module getters

<h3>2.test modular getters State of</h3>
<h5>{{getUserInfo}}</h5>
<h5>{{getUserSex}}</h5>

//Get getters
const getUserInfo = computed(() => store.getters['test/getUserInfo'])
const getUserSex = computed(() => store.getters['test/getUserSex'])

Status of test1 module getters

<h3>2.test1 modular getters State of</h3>
<h5>{{getSport}}</h5>
<h5>{{getPublics}}</h5>

//Get getters
const getSport = computed(() => store.getters['test1/getSport'])
const getPublics = computed(() => store.getters['test1/getPublics'])

4.2.3 using mutations

Change the state of test module age with changes

<h3>3.use mutations change test modular age State of</h3>
<button @click="testClick">change test Status( age)</button>
<h5>{{age}}</h5>

//Change the state through changes and change the age of the test module
const age = computed(() => store.state.test.age)
const testClick = () => {
  store.commit('test/testMutation1')
}

Use changes to change the state of the amount of test1 module

<h3>3.use mutations change test1 modular amount State of</h3>
<button @click="test1Click">change test1 Status( amount)</button>
<h5>{{amount}}</h5>

//Change the status through changes and change the amount of test1 module
const amount = computed(() => store.state.test1.amount)
const test1Click = () => {
  store.commit('test1/test1Mutation1')
}

4.2.4 using actions

Change the status of the test module with actions

<h3>4.use actions change test modular age State of</h3>
<button @click="changeActions">change test Status( age)</button>
<h5>{{age}}</h5>

//Change the status through actions and change the age of the test module
const changeActions = () => {
  store.dispatch('test/testAction1')
}

Use actions to change the state of amount in test1 module

<h3>4.use actions change test1 modular amount State of</h3>
<button @click="changeActions1">change test Status( amount)</button>
<h5>{{amount}}</h5>

//Change the status through actions and change the amount of the test module
const changeActions1 = () => {
  store.dispatch('test1/test1Action1')
}

Complete Demo example

<template>
  <div>
    <h2>Vuex State learning</h2>
    <div class="wrapper">
      <div class="left-box">
        <h3>1.test modular state State of</h3>
        <h5>{{userName}}</h5>
        <h5>{{userInfo}}</h5>
        ----------------------------------------------------------
        <h3>2.test modular getters State of</h3>
        <h5>{{getUserInfo}}</h5>
        <h5>{{getUserSex}}</h5>
        ----------------------------------------------------------
        <h3>3.use mutations change test modular age State of</h3>
        <button @click="testClick">change test Status( age)</button>
        <h5>{{age}}</h5>
        ----------------------------------------------------------
        <h3>4.use actions change test modular age State of</h3>
        <button @click="changeActions">change test Status( age)</button>
        <h5>{{age}}</h5>
      </div>

      <div class="line"></div>
      <div class="right-box">
        <h3>1.test1 modular state State of</h3>
        <h5>{{sport}}</h5>
        <h5>Official account:{{publics}}</h5>
        ----------------------------------------------------------
        <h3>2.test1 modular getters State of</h3>
        <h5>{{getSport}}</h5>
        <h5>{{getPublics}}</h5>
        ----------------------------------------------------------
        <h3>3.use mutations change test1 modular amount State of</h3>
        <button @click="test1Click">change test1 Status( amount)</button>
        <h5>{{amount}}</h5>
        ----------------------------------------------------------
        <h3>4.use actions change test1 modular amount State of</h3>
        <button @click="changeActions1">change test Status( amount)</button>
        <h5>{{amount}}</h5>
      </div>
    </div>

  </div>
</template>
<script setup>
import { computed } from 'vue'
import { useStore } from 'vuex'
const store = useStore()
/* ------------test Module status-----------------*/
//Get the status of test1 module
const userName = computed(() => store.state.test.name)
const userInfo = computed(
  () => store.state.test.name + 'My occupation is:' + store.state.test.profession
)
//Get getters
const getUserInfo = computed(() => store.getters['test/getUserInfo'])
const getUserSex = computed(() => store.getters['test/getUserSex'])

//Change the state through changes and change the age of the test module
const age = computed(() => store.state.test.age)
const testClick = () => {
  store.commit('test/testMutation1')
}

//Change the status through actions and change the age of the test module
const changeActions = () => {
  store.dispatch('test/testAction1')
}

/* -----------test1 Module status------------------*/
//Get the status of test2 module
const publics = computed(() => store.state.test1.publics)
const sport = computed(
  () => store.state.test1.name + 'Favorite sports:' + store.state.test1.sport
)
//Get getters
const getSport = computed(() => store.getters['test1/getSport'])
const getPublics = computed(() => store.getters['test1/getPublics'])

//Change the status through changes and change the amount of test1 module
const amount = computed(() => store.state.test1.amount)
const test1Click = () => {
  store.commit('test1/test1Mutation1')
}

//Change the status through actions and change the amount of the test module
const changeActions1 = () => {
  store.dispatch('test1/test1Action1')
}
</script>

<style scoped>
h2 {
  text-align: center;
}
.wrapper {
  width:1200px;
  margin: 0 auto;
}
.left-box,
.right-box {
  width:calc(50% - 4px);
  display: inline-block;
  text-align: center;
  background: #c4bebf;
  border-radius: 5px;
}
.line {
  height: 100%;
  width: 4px;
  display: inline-block;
}
</style>

5. Plug in

Vuex's store accepts the plugins option, which exposes the hook of each mutation. Vuex plug-in is a function that receives store as the only parameter:

const myPlugin = (store) => {
  // When store is initialized, it is called.
  store.subscribe((mutation, state) => {
    // After each mutation, the call is made.
    // The format of mutation is {type, payload}
  })
}

5.1 using plug-ins

const store = createStore({
  plugins: [myPlugin]
})

The above is the use of vuex and the explanation of some parameters. We make a little progress every day. Welcome to learn and communicate together. It's me. Articles are updated to personal blogs from time to time( https://zhanhongzhu.top ), Nuggets, think and WeChat official account. Strive together and grow together.

Reference articles

vuex Chinese document: https://vuex.vuejs.org/zh/

Topics: Javascript Front-end Vue