# Vuex

# Vuex 的优缺点

  • 方便进行全局的数据管理,因为 Vuex 是响应式的,所以在跨级组件传递参数或者多个同级组件需要同一份参数的时候可以使用 Vuex 进行管理
  • 因为页面刷新导致浏览器申请的堆栈内存被释放,所以当页面刷新的时候 Vuex 的值会丢失

# Vuex 的五大属性

# state

  • 保存全局数据的地方,Vuex 本身规范不允许直接修改 state

    // 实例化
    import { createStore } from "vuex";
    const store = createStore({
      state: {
        count: 1,
        arr: [1, 2, 3, 4],
      },
    });
    // 调用
    this.$store.state.xxx;
    

# getters

  • getters 相当于一个没有缓存的 computed,也可以理解为一个数据处理方法合集。

  • 在 getters 中处理的值都不会直接涉及 state 的变化而是从 state 中取出数据进行一个额外的转变

  • 在 getters 中的处理函数最好是涉及对某一全局数据的多次重复处理,如果只是单次变幻其实没有必要写在 getters 中

    // 实例化
    import { createStore } from "vuex";
    const store = createStore({
      state: {
        count: 1,
        arr: [1, 2, 3, 4],
      },
      getters: {
        changeCount(state) {
          return state.count++;
        },
      },
    });
    // 调用
    this.$store.getters.changeCount;
    

# mutations

  • 官方定义的直接修改 state 的入口,且里面不能涉及异步操作

  • 对于 mutation ,其实是可以在内部进行异步操作的,其实对于 Vuex 来说,mutation 的存在是为了 VueDevtools 能更好的追踪到 state 的状态变化便于调试

    对于本身的使用来讲其实不存在什么异步竞态等问题的

  • mutation 中不写异步是因为 mutation 会对 state 变更前后的状态做一次记录,这样在 vueDevtools 中就会存在一个数据变更的时间线(timeline),但是如果存在异步就会导致 mutation 执行完毕但异步回调函数并没有执行的情况出现就会导致无法追踪

  • 在我自己的调试中发现其实 Vuex 的设计思想应该是对于每一次的 state 变动都应该提交一次 mutation 才能保证 VueDevtools 追踪变化,所以问题的本质根本不是同步和异步的问题。即便你在 mutation 中写的全部都是同步代码但如果涉及 state 的多次变动在 VueDevtools 中的追踪仍然只有一次,所以应当是所有的 mutation 中的 state 变化都只应该有一次,存在多次变化的时候就需要使用 actions 来做提交。但其实我个人认为 mutation 在 Vuex 中根本没有暴露给用户的必要,用户只要对 actions 进行操作,一旦涉及 state 变化就自动触发一次 mutation,这也是为什么 pinia 中没有 mutation 的原因吧

    // 实例化
    import { createStore } from "vuex";
    const store = createStore({
      state: {
        count: 1,
        arr: [1, 2, 3, 4],
      },
      mutation: {
        changeCount(state) {
          state.count++;
        },
      },
    });
    // 调用
    this.$store.commit("changeCount");
    

# actions

  • 可包含任意操作的变更,当需要对 state 进行变化时调用 mutation 中的处理方法即可

  • actions 无法处理异步竞态问题

  • 1.2.3 中 mutation 无法追踪异步回调的问题就变成了转移到 action 中进行操作,即只要出现数据变更就在 action 中对 mutation 进行一次提交,此时在 mutation 中只存在对 state 数据变更的同步代码,因此会就能保证每一次的变更都能被捕获

    // 实例化
    import { createStore } from "vuex";
    const store = createStore({
      state: {
        count: 1,
        arr: [1, 2, 3, 4],
      },
      mutation: {
        changeCount(state) {
          state.count++;
        },
        reduceCount(state) {
          state.count--;
        },
      },
      addCount(context) {
        new Promise((resolve) => {
          context.commit("addCount");
          resolve();
        }).then(() => {
          context.commit("reduceCount");
        });
      },
    });
    // 调用
    this.$store.dispatch("changeCount");
    

# moudules

  • 模块化,本质就是多个 store 分开进行管理,官方说是用于大型项目的数据管理

  • 我个人认为 modules 并没有什么很大的作用,实际上我们本身也可以通过对象的 key——value 来进行数据的划分

  • modules 中的 state 要写成一个函数

    // 实例化
    import {createStore} from "vuex";
    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 的状态