前端笔记 -- Vuex | 青训营笔记

84 阅读3分钟

这是我参与「第四届青训营 」笔记创作活动的第九天
今天学习了与vuex相关的东西,下面让我浅浅介绍一下Vuex

什么是 Vuex

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

image.png

Vuex 的核心概念

Vuex 的内脏由五部分组成:State、Getter、Mutation、Action 和 Module。

State

State一般用于保存具体的数据

import Vue from 'vue' 
import Vuex from 'vuex' 
//使用vuex Vue.use(Vuex) 
//导出store 
export default new Vuex.Store({ 
//将数据定义在state里面,state是一个对象 
state: { count: 0 }
})

mapState

当一个组件需要获取多个状态的时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用 mapState 辅助函数帮助我们生成计算属性

import { mapState } from 'vuex'

// 对象写法
computed:{
    ...mapState({
     a:'xx',
     b:'xxx'
    })
}

// 数组写法  (当映射的计算属性的名称与 state 的子节点名称相同时)
computed:{
    ...mapState(['xxx','xx'])
}

Getter

有时候我们需要从 store 中的 state 中派生出一些状态,例如对列表进行过滤并计数。如果有多个组件需要用到此属性,我们可以使用Getter:

const store = createStore({
 state: {
   todos: [
     { id: 1, text: '...', done: true },
     { id: 2, text: '...', done: false }
   ]
 },
 getters: {
   doneTodos (state) {
     return state.todos.filter(todo => todo.done)
   }
 }
})

mapGetters

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

import { mapGetters } from 'vuex'

export default {
  // ...
  computed: {
  // 数组写法 (当映射的计算属性的名称与 state 的子节点名称相同时)
    ...mapGetters([
      'doneTodosCount',
      'anotherGetter',
      // ...
    ])
  }
}


// 对象写法
...mapGetters({
  // 把 `this.doneCount` 映射为 `this.$store.getters.doneTodosCount`
  doneCount: 'doneTodosCount'
})

Mutation

更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的事件类型 (type)和一个回调函数 (handler)

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

调用mutations中的函数要使用 store.commit 方法:

store.commit('increment')

mapMutations

除了在组件中使用 this.$store.commit('xxx') 提交 mutation,也可以使用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')`
    })
  }
}

Action

Action 提交的是 mutation,而不是直接变更状态。
Action 可以包含任意异步操作。

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

Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。 组件中通过 store.dispatch 方法触发:

store.dispatch('increment')

mapActions

在组件中除了使用 this.$store.dispatch('xxx') 分发 action,也可以使用 mapActions 辅助函数

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

当应用变得非常复杂时,store 对象就有可能变得相当臃肿。为了解决以上问题,Vuex 允许我们将 store 分割成模块(module) 。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割

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

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

const store = createStore({
 modules: {
   a: moduleA,
   b: moduleB
 }
})

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

命名空间

通过添加 namespaced: true 的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。例如:

const store = createStore({
  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']
          }
        }
      }
    }
  }
})

总结

本文主要介绍了vuex中最重要的核心概念以及其相关的用法和代码,希望本文能对不熟悉vuex的同学有一定的帮助。

参考

vue官方文档