Day 11: State Management VueX

Introduction to VueX

A brief introduction to VueX

  • For componentized development, the state of a large application often spans multiple components. It is very troublesome to transfer state between multi-layer nested parent-child components, and Vue does not provide a way for sibling components to directly share data.
  • Based on this problem, many frameworks provide solutions - use a global state manager to hand over all decentralized shared data to the state manager for safekeeping, and Vue is no exception.
  • Vuex is a state management library specially developed for Vue.js applications, which uses centralized storage to manage the state of all components of the application.
  • Simply put, Vuex is used to manage data scattered in various components of Vue.
  • VueX installation: npm install vuex@next (install the latest version)

state management

  • Vuex is not necessary for use in more complex website development.
  • The core of every Vuex application is a store (the unified instance in vuex, the global object, and the data to be shared by all components can be stored inside the store, maintained and managed by it), which is different from ordinary global objects. Based on the characteristics of Vue data and view binding, when the state in the store changes, the view bound to it will also be re-rendered (the store is bound to the view ) .
  • The state in the store is not allowed to be modified directly. The only way to change the state in the store is to explicitly submit (commit) the mutation, which allows us to easily track each state change (easy to maintain).
  • In large and complex applications, if state changes cannot be effectively tracked, it will cause great trouble to understand and maintain the code.
  • There are 5 important concepts in Vuex: State, Getter, Mutation, Action, Module.
    insert image description here
    If there is an asynchronous request, the Action is triggered through Dispatch, and the Action submits the Mutation to finally modify the data in the State; if there is no asynchronous operation, the component can also directly submit the Mutation to modify the value in the State.
    Introduction to the use process of 5 important concepts in Vuex:
    The following code is based on vue3, namely vuex4
    1. State
      State is used to maintain the state of all application layers and ensure that the application has only one data source.
      insert image description here
      In components, you can directly use this.$store.state.count to access data, or use the mapState auxiliary function to map it first
      insert image description here
    2. Getter
      Getter maintains some states derived from State, and these states change with the state of State (for example, State stores some to-do items, if completed is true, not completed is false, in this interface you may want to display all completed ones, or display all unfinished ones). In components, you can use this.$store.getters.doneTodos directly, or use the mapGetters auxiliary function to map it first, the code is as follows
      insert image description here
      :
      insert image description here
    3. Mutation
      Mutation provides methods to modify the State state.
      insert image description here
      In the component, you can directly use store.commit to submit the mutation
      insert image description here
      , or use the mapMutation auxiliary function to map it first
      insert image description here
    4. Action
    • Only some synchronous operations can be done in Mutation. In order to track the state changes, if it is some asynchronous operation, use Action

    • Action is similar to Mutation, the difference is that: Action cannot directly modify the state, but can only be modified by submitting mutation, and Action can contain asynchronous operations.

    • Action is also defined in the method, the parameter is context (context object), instead of directly modifying the state, but submitting mutation. (For example, the data obtained by the network request needs to update the data in the State, and use the context to submit the mutation, and then indirectly modify the data in the State. The reason for this design is to record the changes in the State in the Action)
      insert image description here

      In the component, you can directly use this.$store.dispatch('xxx') to distribute the action, or use the mapActions auxiliary function to map it first
      insert image description here

VueX installation and use

VueX installation

Method 1 :
Select the vuex module to install when creating a vue project
insert image description here
Method 2 :
Use npm install to install

vue2: npm install vuex@3
vue3: npm install vuex@4

VueX uses

VueX uses about State

src/store/index.js

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

Vue.use(Vuex)

const store = new Vuex.Store({
    
    
    state: {
    
    
        count: 0
    },
    mutations: {
    
    
        increment(state) {
    
    
            state.count++
        }
    }
})
export default store

main.js

import Vue from 'vue'
import App from './App.vue'
import store from './store'

Vue.config.productionTip = false

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

HelloWorld.vue

<template>
  <div class="hello">
      {
   
   { this.$store.state.count }}
      <button @click="add">+1</button>
  </div>
</template>

<script>
export default {
      
      
  name: 'HelloWorld',
  methods:{
      
      
    add(){
      
      
      // this.$store.state.count = this.$store.state.count +1
      this.$store.commit("increment")
    }
  }
  
}
</script>

HelloWorld.vue is easier to write
insert image description here
or
use the mapState helper function
to import in the components that need to be used:

import {
    
     mapState } from 'vuex'

Modify the computed part (the following three methods are available):

 computed: mapState({
    
    
    // 箭头函数可使代码更简练
    count: state => state.count,

    // 传字符串参数 'count' 等同于 `state => state.count`
    countAlias: 'count',

    // 为了能够使用 `this` 获取局部状态,必须使用常规函数
    countPlusLocalState (state) {
    
    
      return state.count + this.localCount
    }
  })

We can also pass an array of strings to mapState when the name of the mapped computed property is the same as the name of the child node of the state.

computed: mapState([
  // 映射 this.count 为 store.state.count
  'count'
])

VueX uses About Getter

src/store/index.js
insert image description here
uses mapGetters, code example:
HelloWorld.vue

<template>
  <div class="hello">
      <!-- {
    
    { this.$store.state.count }} -->
      {
   
   { count }}
      <button @click="add">+1</button>

      <!-- Getter -->
      <ul>
      <li v-for="todo in doneTodos" :key="todo.id">{
   
   { todo.text }}</li>
    </ul>
  </div>
</template>
<script>
import {
      
       mapState,mapGetters } from 'vuex'
export default {
      
      
  name: 'HelloWorld',
  //mapState与mapGetters同时使用
  computed:{
      
      
      ...mapState([
    'count','todos'
      ]),
      ...mapGetters([
          'doneTodos'
      ])
  },
  methods:{
      
      
  add(){
      
      
    // this.$store.state.count = this.$store.state.count +1
    this.$store.commit("increment")
  }
}
  
}
</script>

VueX uses about Mutation

Additional parameters can be passed to store.commit, that is, the payload of the mutation:
src/store/index.js

mutations: {
    
    
        // increment(state) {
    
    
        //     state.count++
        // }
        increment(state, n) {
    
    
            state.count += n
        }
    },

HelloWorld.vue

methods:{
    
    
  add(){
    
    
    // this.$store.state.count = this.$store.state.count +1
    this.$store.commit("increment",2)
  }
}

You can use this.$store.commit('xxx') in the component to submit the mutation, or use the mapMutations auxiliary function to map the methods in the component to the store.commit call (need to inject the store at the root node).

import {
    
     mapMutations } from 'vuex'

export default {
    
    
  // ...
  methods: {
    
    
    ...mapMutations([
      'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')`

      // `mapMutations` 也支持载荷:
      'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
    ]),
    ...mapMutations({
    
    
      add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')`
    })
  }
}

VueX uses about Action

The reason to abstract Action is to record the state changes of asynchronous data
Register a simple Action
src/store/index.js

const store = new Vuex.Store({
    
    
  state: {
    
    
    count: 0
  },
  mutations: {
    
    
    increment (state) {
    
    
      state.count++
    }
  },
  actions: {
    
    
    increment (context) {
    
    
      context.commit('increment')
    }
  }
})

Dispatch Action
Action is triggered by store.dispatch method:

store.dispatch('increment')

Distribute Actions in Components
Use this.$store.dispatch('xxx') to distribute actions in components, or use the mapActions auxiliary function to map component methods to store.dispatch calls (the store needs to be injected into the root node first):

HelloWorld.vue

import {
    
     mapActions } from 'vuex'

export default {
    
    
  // ...
  methods: {
    
    
    ...mapActions([
      'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`

      // `mapActions` 也支持载荷:
      'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
    ]),
    ...mapActions({
    
    
      add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
    })
  }
}

VueX uses about Module

If the application data is particularly large, vue allows split modules.
Vuex allows us to split the store into modules. Each module has its own state, mutation, action, getter, and even nested submodules—separated in the same way from top to bottom:

const moduleA = {
    
    
  state: () => ({
    
     ... }),
  mutations: {
    
     ... },
  actions: {
    
     ... },
  getters: {
    
     ... }
}

const moduleB = {
    
    
  state: () => ({
    
     ... }),
  mutations: {
    
     ... },
  actions: {
    
     ... }
}

const store = new Vuex.Store({
    
    
  modules: {
    
    
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态

Guess you like

Origin blog.csdn.net/weixin_46443403/article/details/129044674