AkiraZ's blog

愿键盘的余温传递到更遥远的将来

中文 / English
0%

Vuex

官方手册

https://vuex.vuejs.org/zh/

核心概念

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);

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

一个简单的示例

State

  • 一个全局的状态

  • 响应式

  • 必须显式提交更改

  • 一般读由 mutation 执行,写由 getter 执行

  • 也可以直接访问 this.$store.state.VAR_NAME

  • 可以使用 computed 监听该属性

    1
    2
    3
    4
    5
    6
    7
    8
    const Counter = {
    template: `<div>{{ count }}</div>`,
    computed: {
    count() {
    return this.$store.state.count;
    },
    },
    };

Getters

  • 读取 store 值,允许同时做一点处理

    Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。

  • Getter 接受 state 作为其第一个参数

  • Getter 也可以接受其他 getter 作为第二个参数

    1
    2
    3
    4
    5
    6
    7
    8
    getters: {
    doneTodos: state => {
    return state.todos.filter(todo => todo.done)
    },
    doneTodosCount: (state, getters) => {
    return getters.doneTodos.length
    }
    }
  • 调用:访问 this.$store.getters.METHOD_NAME()

Mutations

  • 允许通过 mutation 更改 store

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

  • 必须同步执行

  • 第一参数 state ,第二参数传入的 payload

    1
    2
    3
    4
    5
    mutations: {
    increment (state, payload) {
    state.count += payload.amount
    }
    }
  • 调用,两种方式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    // 调用 increment 方法
    store.commit("increment", {
    amount: 10,
    });

    store.commit({
    type: "increment",
    amount: 10,
    });

Actions

  • 可以调用 mutation 达成状态变更,但是不能直接操作

  • 支持异步

  • 第一参数 context 类似 store

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

  • 推荐使用解构

  • 使用 dispatch 来调用 action

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    actions: {
    incrementAsync ({ commit }) {
    setTimeout(() => {
    commit('increment')
    }, 1000)
    }
    }

    // 以载荷形式分发
    store.dispatch('incrementAsync', {
    amount: 10
    })

    // 以对象形式分发
    store.dispatch({
    type: 'incrementAsync',
    amount: 10
    })
  • 由于返回的是 Promise 所以可以照常处理

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    actions: {
    // ...
    actionB ({ dispatch, commit }) {
    return dispatch('actionA').then(() => {
    commit('someOtherMutation')
    })
    }
    }

    // 或者使用 await
    actions: {
    async actionA ({ commit }) {
    commit('gotData', await getData())
    },
    async actionB ({ dispatch, commit }) {
    await dispatch('actionA') // 等待 actionA 完成
    commit('gotOtherData', await getOtherData())
    }
    }

Modules

  • 模块化的管理模式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    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 的状态
  • 暂时还没用上,留个地址

    https://vuex.vuejs.org/zh/guide/modules.html

Misc

结构

1
2
3
4
5
6
7
└── store
├── index.js # 我们组装模块并导出 store 的地方
├── actions.js # 根级别的 action
├── mutations.js # 根级别的 mutation
└── modules
├── cart.js # 购物车模块
└── products.js # 产品模块