Vuex学习笔记

350 阅读1分钟

0. 参考

  1. Vuex 官方文档
  2. 这次彻底搞懂Vuex!(小白级别教程) - 掘金 (juejin.cn)
  3. VueX(Vue状态管理模式) - 简书 (jianshu.com)

1. 前言

本文仅为个人学习笔记,并非教学文章,仅适合在过完文档或其他教程后再来阅读巩固一遍。如需教学文章,可阅读上一部分参考文献

2. 何为Vuex

Vuex是应用于Vue的状态管理模式[1],或者用一个耳熟能详的词:外挂。Vuex这个外挂为什么要使用?搞懂这个问题才能知道Vuex的由来。

如果不使用Vuex开发,那么组件之间通信用$emit$refs等语法糖即可搞定。但一旦项目非常大呢?比如100个组件之间通过父子组件通信等方式形成了一张错综复杂的关系网,而这些关系网都要用到共同的数据字段,如时间、地点、人物等。将获取这些数据字段data写在一个组件中,在该组件中用$emit等方式传出去,然后在其他组件中用props或者监听自定义事件的方式等传出去,理论上虽然可以,但一想到还要像走迷宫似的找到传播路径,理清组件辈分关系...理着理着就乱糟糟还容易理错。那么,如果将这些公共数据放到一个外挂中,项目中组件老少咸宜都能用这些数据,就不用再走传播路径迷宫了,这不就省下许多事了?

这就是Vuex的实质。

3. Vuex的五大核心内容

根据官方文档[1],Vuex有五大核心概念:StateGettersMutationsActionsModules。下文对其一一分解。

3.1 一个简单的实例

以下为官方提供的简单示例代码[1],仅在末尾添加了分号。

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

Vue.use(Vuex);

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

3.2 State

从上述代码来看,实际上可以将state理解为组件中的data

3.3 Mutations

可以被理解为methods

3.4 Getters

官方示例代码[1],仅于末尾添加分号。

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);
    },
  },
});

可以从代码中看出,getter表现的与计算属性非常相似。

3.5 Actions

官方示例代码[1],仅于末尾添加分号。

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

同时,根据官方文档,我们可以将actions理解如下:

  • 管理mutations的方法,也就是“方法的方法”
  • 可以异步的方法(mutations无法异步)

3.6 Modules

每一组statemutationsgettersmodules均为一个module。当需要定义的数据与状态太多的时候,可以开不只一个外挂(module),可以定义不同的外挂,随用随挂载。

4. 使用Vuex

4.1 全局引入

在根目录中建立一个store文件夹来管理状态,而后在main.js中将其全局引入。示例代码来自博客[2]。 主

// main.js

import Vue from 'vue';
import App from './App';
//引入store 
import store from './store';

new Vue ({
    el: "#app",
    // 重点在这里
    store,
    components: {
        App,
    },
    template: '<App />',
});

4.2 在组件中使用state

两种方式:

  • 使用计算属性
  • mapState函数

使用计算属性如下(官方代码):

const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count () {
      return store.state.count;
    },
  },
};

使用mapState()方法如下(官方代码):

// 在单独构建的版本中辅助函数为 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: {
  localComputed () { /* ... */ },
  // 使用对象展开运算符将此对象混入到外部对象中
  ...mapState({
    // ...
  })
}

4.3 在组件中使用getters

使用mapGetters方法

import { mapGetters } from 'vuex';

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

4.4 在组件中使用mutations

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

4.5 分发actions

同理,在组件中可以用mapActions分发。