快速了解Vuex

Vuex快速学习

前情提要

本文旨在快速了解Vuex相关使用方法,同时也想通过记录博客的方式记录笔记。

Vuex是什么

Vuex是Vue官方提供的状态管理器,为多个组件共享状态时提供的解决方案。

vuexvuex

Vuex例子

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

Vue.use(Vuex)

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

//调用

this.$store.commit('increment')

console.log(this.$store.state.count) // -> 1

要了解一个组件如何使用,先了解一下组件的核心概念吧。

Vuex核心概念

State

Vuex存储共享数据的对象

  1. 数据访问方式this.$store.state.属性名称

  2. 数据修改方式: 参见Mutation、Action

  3. mapState辅助函数:当一个组件需要获取多个状态的时候,将这些状态都声明为计算属性会有些重复和冗余,那就需要使用mapState。

    • 使用方式1

      //在单独构建的版本中辅助函数为 Vuex.mapState
      import { mapState } from 'vuex'
      export default {
        // ...
        computed: mapState({
          // 箭头函数可使代码更简练
          count: state => state.count,

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

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


      //简写
      computed: mapState([
        // 映射 this.count 为 store.state.count
        'count'
      ])
    • 使用方式2

      computed: {
        localComputed () { /* ... */ },
        // 使用对象展开运算符将此对象混入到外部对象中
        ...mapState({
          // ...
        })
      }

Getter

提供共享的数据的计算属性,减少在组件内部写计算属性的冗余。

  1. 使用方式

    //Getter 接受 state 作为其第一个参数
    const store = new Vuex.Store({
      state: {
        todos: [
          { id: 1, text: '...', done: true },
          { id: 2, text: '...', done: false }
        ]
      },
      getters: {
        doneTodos: state => {
          return state.todos.filter(todo => todo.done)
        }
      }
    })

    //调用
    this.$store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }]



    //传参方式
    //通过让 getter 返回一个函数,来实现给 getter 传参
    getters: {
      // ...
      getTodoById: (state) => (id) => {
        return state.todos.find(todo => todo.id === id)
      }
    }
    //调用
    this.$store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }

  2. 调用方式: this.$store.getters.属性名称

  3. mapGetters辅助函数:将 store 中的 getter 映射到局部计算属性

    • 使用方式

      import { mapGetters } from 'vuex'

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


      //起别名
      ...mapGetters({
        // 把 `this.doneCount` 映射为 `this.$store.getters.doneTodosCount`
        doneCount: 'doneTodosCount'
      })

Mutation

更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。

  1. 使用方式

    const store = new Vuex.Store({
      state: {
        count: 1
      },
      mutations: {
        increment (state) {
          // 变更状态
          state.count++
        },
        increment (state, n) {
           state.count += n
        }
      }
    })



    //调用方式1
    this.$store.commit('increment')

    //调用方式2    payload 传参
    this.$store.commit('increment',10)

    //调用方式3    对象风格的提交方式

    this.$store.commit({
      type: 'increment',
      amount: 10
    })
  2. mapMutations辅助函数:简化组件调用。

    • 使用方式
    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')`
        })
      }
    }
  3. 遵守相关规范

    • Mutation 必须是同步函数

Action

Action 类似于 mutation,不同在于:

  • Action 提交的是 mutation,而不是直接变更状态。

  • Action 可以包含任意异步操作。

    注意:Action 提交 mutation ,mutation 修改store。

  1. 使用方式

    const store = new Vuex.Store({
      state: {
        count: 0
      },
      mutations: {
        increment (state) {
          state.count++
        },
        increment (state, n) {
           state.count += n
        }
      },
      actions: {
        increment (context) {
          context.commit('increment')
        },
          
        //异步方式  
        incrementAsync ({ commit }) {
           setTimeout(() => {
           commit('increment')
         }, 1000)
       }
      }
    })



    //调用1
    this.$store.dispatch('increment')

    //调用2     payload 传参
    this.$store.dispatch('increment',{
      amount: 10
    })

    //调用3     对象风格的提交方式
    store.dispatch({
      type: 'incrementAsync',
      amount: 10
    })




    //使用例子
    actions: {
      checkout ({ commit, state }, products) {
        // 把当前购物车的物品备份起来
        const savedCartItems = [...state.cart.added]
        // 发出结账请求,然后乐观地清空购物车
        commit(types.CHECKOUT_REQUEST)
        // 购物 API 接受一个成功回调和一个失败回调
        shop.buyProducts(
          products,
          // 成功操作
          () => commit(types.CHECKOUT_SUCCESS),
          // 失败操作
          () => commit(types.CHECKOUT_FAILURE, savedCartItems)
        )
      }
    }

  2. 组件内调用(分发)方式this.$store.dispatch('action方法名称')

  3. mapActions辅助函数: 类 mapMutations,简化组件分发。

    1. 使用方式

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

Module

Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割

  1. 使用方式:

    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 的状态
  2. 使用细节:使用模块化后mutationsgettersactions参数暴露方式有所不同,具体请参照官方文档

  3. 命名空间:模块内部添加namespaced属性为true

    const store = new Vuex.Store({
      modules: {
          
        account: {
          namespaced: true,

          // 模块内容(module assets)
          state: () => ({ ... }), // 模块内的状态已经是嵌套的了,使用 `namespaced` 属性不会对其产生影响
          getters: {
            isAdmin () { ... } // -> getters['account/isAdmin']
          },
          actions: {
            login () { ... } // -> dispatch('account/login')
          },
          mutations: {
            login () { ... } // -> commit('account/login')
          },

          // 嵌套模块
          modules: {
            // 继承父模块的命名空间
            myPage: {
              state: () => ({ ... }),
              getters: {
                profile () { ... } // -> getters['account/profile']
              }
            },

            // 进一步嵌套命名空间
            posts: {
              namespaced: true,

              state: () => ({ ... }),
              getters: {
                popular () { ... } // -> getters['account/posts/popular']
              }
            }
          }
        }
      }
    })

当你的才华还撑不起你的野心的时候,你就应该静下心来学习。当你的能力还驾驭不了你的目标的时候,你就应该沉下心来历练。

posted @ 2021-08-26 18:31  Hoiwe  阅读(49)  评论(0)    收藏  举报