Vue state management-Vuex

Preface

Reference: Vuex official website , vue.js official website

What is Vuex

Vuex is a state management mode developed specifically for Vue.js applications. 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 manner. Vuex is also integrated into Vue's official debugging tool devtools extension (opens new window), providing advanced debugging functions such as zero-configuration time-travel debugging, state snapshot import and export, etc.

This is the definition of Vuex on the official website, we can see:

  • Vuex is a state management library specially designed for Vue.js
  • The use of centralized management of data that needs to be shared between multiple components in the application solves the problem of complex component communication and realizes data sharing
  • Centrally managed data changes in a predictable way

Vuex application scenarios

Componentization is one of the core of Vue.js. Componentization can bring us faster development efficiency and better maintainability. In a Vue project, each page can be regarded as a component. In most scenarios The components do not exist independently, but cooperate with each other to form a complex business function, which leads to the intricate relationship between the component states, and it is particularly important to manage these states. Through the definition of the official website, we know that the original intention of Vuex design is to solve this problem. Can all Vue.js applications use Vuex?

Vuex can help manage shared state, but it also comes with more concepts and frameworks. If an application is simple enough with only a few simple pages, using Vuex is undoubtedly cumbersome and redundant, which will invisibly increase the development workload and affect Development efficiency. But when we build a medium and large single-page application, multiple components rely on the same state, and multiple components need to change the same state through internal methods, Vuex is the best choice.

Vuex core concepts

Insert picture description here
As can be seen from this picture on the official website, the core of Vuex is state, actions, and mutations.

State
state is the shared state of application components. It is stored in the Vuex core warehouse store to form a single state tree. The states stored in the store are all responsive. When the Vue component reads the state from the store, if the state in the store is If the status changes, the corresponding components will be updated accordingly.

new Vuex.Store({
    
    
  state: {
    
    
    name: 'zhangsan',
    sex: '男',
    age:10
  }
})

There are three ways to get the state in Vuex in the component

  • The easiest way is to obtain by calculating attributes
// 创建一个 Counter 组件
const Counter = {
    
    
   template: `<div>{
     
     { count }}</div>`,
   computed: {
    
    
      count () {
    
    
         return store.state.count
      }
   }
}

  • Via store injected from the root component
// 根组件,把 store 对象提供给 “store” 选项,这可以把 store 的实例注入所有的子组件
const app = new Vue({
    
    
  el: '#app',
  store,
  components: {
    
     Counter },
  template: `
    <div class="app">
      <counter></counter>
    </div>
  `
})

//子组件
const Counter = {
    
    
  template: `<div>{
     
     { count }}</div>`,
  computed: {
    
    
    count () {
    
    
      return this.$store.state.count
    }
  }
}
  • Through the mapState helper function, the mapState function returns an object
import {
    
     mapState } from 'vuex'
//1.基本用法
const Counter = {
    
    
  template: `<div>{
     
     { count }}</div>`,
  computed: mapState({
    
    
      count: state => state.count,
      // 传字符串参数 'count' 等同于 `state => state.count`
      countAlias: 'count',
  })
}

//2.组件中的计算属性名和store中的state名一致时,可以给 mapState 传一个字符串数组
const Counter = {
    
    
  template: `<div>{
     
     { count }}</div>`,
  computed: mapState(['count'])
}

//3.使用对象展开运算符
const Counter = {
    
    
  template: `<div>{
     
     { count }}</div>`,
  computed: {
    
    
     ...mapState(['count'])
  }
}

mutations

  1. Submitting a mutation is the only way to change the state in the Vuex store
  2. Mutations are similar to events, each mutation has a string event type (type) and a callback function (handler)
  3. The first parameter of each mutation callback function must be state (state), and the second optional parameter payload (string or object)
  4. Each mutation must be a synchronous function

Submit the mutation method

//1.提交载荷
mutations: {
    
    
  increment (state, n) {
    
    
    state.count += n
  }
}
store.commit('increment', 10) //载荷是普通值

mutations: {
    
    
  increment (state, payload) {
    
    
    state.count += payload.amount
  }
}
store.commit('increment', {
    
     amount: 10 })//载荷是对象

//2.对象风格提交
mutations: {
    
    
  increment (state, payload) {
    
    
    state.count += payload.amount
  }
}
store.commit({
    
     type: 'increment', amount: 10 })

actions

  1. The action submits the mutation and cannot directly change the state in the store
  2. Each action has a string event type (type) and callback function (handler)
  3. Action can be a synchronous function or an asynchronous function

Distribute Actions through store.dispatch()

//1.不带参数分发
actions: {
    
    
  increment ({
    
     commit }) {
    
    
    commit('increment')
  }
}
store.dispatch('increment')

//2.带参数方式分发
actions: {
    
    
  incrementAsync ({
    
     commit }) {
    
    
    setTimeout(() => {
    
    
      commit('increment')
    }, 1000)
  }
}
store.dispatch('incrementAsync', {
    
     amount: 10 }) //以载荷形式分发
store.dispatch({
    
     type: 'incrementAsync', amount: 10 }) //以对象形式分发

Distribute the action
in the assembly, use this.$store.dispatch('xxx') in the component to distribute the action, or use the mapActions helper function to map the component’s methods to store.dispatch calls (you need to inject store at the root node first)

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')`
    })
  }
}

In addition to the above three main core concepts, there are also getters and modules.
Getters

  • The function of getters is similar to the calculated properties in vue.js. The return value will be cached according to its dependencies, and will be recalculated only when its dependent value changes.
  • The getter receives state as its first parameter and other getters as the second parameter.

Ways to access the getter

//1.通过属性访问(getter会暴露为 store.getters 对象)
getters: {
    
    
  doneTodosCount: (state, getters) => {
    
    
    return getters.doneTodos.length
  }
}
store.getters.doneTodosCount // -> 1

//2.通过方法访问(让 getter 返回一个函数,来实现给 getter 传参)
getters: {
    
    
  getTodoById: (state) => (id) => {
    
    
    return state.todos.find(todo => todo.id === id)
  }
}
store.getters.getTodoById(2)

//3.通过mapGetters辅助函数
import {
    
     mapGetters } from 'vuex'

export default {
    
    
  computed: {
    
    
     // 使用对象展开运算符将 getter 混入 computed 对象中
    ...mapGetters([
      'doneTodosCount',
      'anotherGetter',
      // ...
    ])
  }
}

Modules

  • In case the store is too large and complicated, Vuex allows us to divide the store into modules from top to bottom, each module has its own
    state, mutation, action, getter, and even nested submodules.
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 的状态

  • Module's local state
    The mutation and getter inside the module, the first parameter received is the module's local state object
const moduleA = {
    
    
  state: () => ({
    
    
    count: 0
  }),
  mutations: {
    
    
    increment (state) {
    
    
      // 这里的 `state` 对象是模块的局部状态
      state.count++
    }
  },

  getters: {
    
    
    doubleCount (state) {
    
    
      return state.count * 2
    }
  }
}

For actions inside the module, context.state is the local state, and context.rootState is the root node state

const moduleA = {
    
    
  actions: {
    
    
    incrementIfOddOnRootSum ({
    
     state, commit, rootState }) {
    
    
      if ((state.count + rootState.count) % 2 === 1) {
    
    
        commit('increment')
      }
    }
  }
}

For the getter inside the module, the third parameter is the root node state

const moduleA = {
    
    
  getters: {
    
    
    sumWithRootCount (state, getters, rootState) {
    
    
      return state.count + rootState.count
    }
  }
}

Guess you like

Origin blog.csdn.net/weixin_41269811/article/details/111959412