导航
导航
文章目录
  1. Vuex核心思想
    1. 一个简单的例子
  2. Vuex核心概念
    1. State
      1. 在Vue组件中获得Vuex状态
      2. mapState辅助函数
    2. Getter
      1. mapGetters辅助函数
    3. Mutation
      1. 提交载荷
      2. Mutation必须是同步函数
      3. 在组件中提交Mutation
    4. Action
      1. 触发Action
    5. Module

Vuex学习笔记

在最近开发的两个还比较大型的项目中,都用到了Vuex来管理状态,Vuex官网上的定义是,Vuex是一个专门为Vue.js应用程序开发的状态管理模式,采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。也就是,Vuex提供了一个不同组件间通信的方式,不再是只有父子组件才能实现通信,其他任何组件之间都能通过Vuex来实现通信。所以,Vuex适合在比较复杂和大型的单页应用中使用,小型简单的应用就没必要了,用了反而繁琐。

Vuex核心思想

Vuex应用的核心是store(仓库)。store就是一个容器,包含着应用中大部分的状态(即state)。Vuex和单纯的全局对象有以下两点不同:

  1. Vuex的状态存储是响应式的,当Vue组件从store中读取状态的时候,若store中的状态发生变化,那么相应的组件也会得到高效更新。
  2. 不能直接改变store中的状态,改变store中的状态唯一途径就是显式地提交mutations,这样可以方便地追踪每一个状态变化。

一个简单的例子

1
2
3
4
5
6
7
8
9
10
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++;
}
}
});

在Vue实例中,可以通过store.state来获取Vuex对象,并通过store.commit方法来触发状态变更。

1
store.commit('increment');

Vuex核心概念

Vuex核心概念主要有State、Getter、Mutation、Action和Module几个。

State

Vuex使用了单一状态树,一个store对象就存储了整个应用层的状态,让我们可以更方便地定位到某一个具体的状态,在调试时能简单获取到当前整个应用的快照。

  1. 要使用store,首先必须Vue.use(vuex),然后将store(const store = new Vuex.store()) inject定义到Vue实例app中new Vue({store}),实现从根组件注入到所有子组件中,接着就可以在子组件中使用this.$store调用了。
  2. 当一个组件需要使用多个某store的状态属性或getters,可以使用shared helper – 共享帮手 mapState,他会返回一个对象。 在mapState里面我们既可以调用store的state,也可以调用store的getters。

在Vue组件中获得Vuex状态

由于Vuex的状态存储是响应式的,从store实例中读取状态最简单的方法就是在计算属性中返回某个状态。
Vuex通过store选项,提供了一种机制将状态从根组件注入到每一个子组件中。通过在根实例中注册store选项,该store实例会注入到根组件下的所有子组件中,且子组件能通过this.$store访问到。

mapState辅助函数

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

Getter

Vuex提供了getters属性,用途类似stores的计算属性,getters中的方法接受两个参数,分别为state以及getters(其他getters),用法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
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会暴露为store.getters对象。

mapGetters辅助函数

可将store的getters映射到本地的计算属性中来,除了可以使用数组之外,还可以使用对象起别名。

1
2
3
4
...maoGetters([
'doneTodoCount',
'anotherGetter',
])

Mutation

能改变Vuex store中的state状态的唯一方法是提交mutation变更。mutation和事件很像:都有字符串类型的type以及handle句柄。我们在handler中实际修改state,state为每个mutation的第一个参数。

1
2
3
4
5
6
7
8
9
10
11
const store = new Vuex.Store({
state: {
conut:1
},
mutations: {
increment(state) {
state.count++
}
}
});
store.commit('increment');

提交载荷

commit的第二个可选参数为payload有效载荷,可以为普通类型或对象类型等等。commit方法还可以通过对象形式调用,这种情况下,该对象就被当成payload。

1
2
3
4
5
6
7
8
9
10
store.commit({
type:'increment',
amount: 10
});
// ...
mutations: {
increment (state, payload) {
state.count += payload.amount
}
}

Mutation必须是同步函数

Mutation必须都是同步的,它的改变必须在调用之后立即执行,因为它是唯一可以修改state的,如果他使用了异步方法,将会使我们的state无法追踪,定位问题也变得十分困难。

在组件中提交Mutation

在组件中commit mutation时,可以使用this.$store.commit()或者使用mapMutations方法,后者可以将组件中的方法映射到store.commit调用。

Action

Action是提交Mutation的,它可以有任意的异步操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit('increment')
}
}
});

触发Action

Action通过store.dispatch方法触发:

1
store.dispatch('increment');

Module

由于Vuex使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store对象就有可能变得相当臃肿。为了解决以上问题,Vuex允许将store分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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 的状态

Vuex的学习主要是通过官方文档和实战,Vue及其相关产品的文档都写得很清楚,对初学者十分友好。

本文总阅读量: