Vuex

什么是Vuex?

Vuex 是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间的数据共享.

image-20200710180830043

如何没有vuex,我们大范围的传值的时候会十分麻烦,而有了vuex 我们只需要跟store相互就可以了

当然我们也不是所有的数据都需要放到vuex中,有一些组件私有的数据,我们没有必要把他放到vuex中,只有组件之间共享的数据,才有必要放到vuex中.

使用vuex统一管理状态的优点:

  1. 能够在vuex中几种管理共享的数据,易于开发和维护.
  2. 能够高效的实现组件之间的数据共享,提供开发效率.
  3. 存储在vuex中的数据都是响应式的,能够实时保持数据与页面的同步

Vuex的基本使用

安装vuex依赖包

1
2
npm install vuex --save
# 当然你也可以用 cnpm

导入vuex包

1
2
3
4
import Vue from "vue";
import Vuex from "vuex";
//将vuex放入vue中
Vue.use(Vuex);

创建store对象

1
2
3
4
5
6
export default new Vuex.Store({
state: {},
mutations: {},
actions: {},
modules: {}
});

将store对象挂载到vue实例中

1
2
3
4
5
6
7
8
9
10
11
12
13
import Vue from "vue";
import App from "./App.vue";
// 导入store组件中的store实例对象
import store from "./store";

Vue.config.productionTip = false;

new Vue({
//将创建的共享数据对象,挂载到vue实例中
//所有组件都可以从store中获取数据
store,
render: h => h(App)
}).$mount("#app");

vuex的核心概念

State

提供唯一的公共数据源,所有的共享数据都统一放到Store的state中进行存储

声明数据
1
2
3
4
export default new Vuex.Store({
state: {
count: 0
},
组件访问state中的数据

第一种方式:this.$store.state.全局数据名称

第二种方式:

1
2
3
4
5
6
7
//从vuex中按需导入mapState 函数
import {mapState} from 'vuex'
//通过刚才导入的mapState函数,将当前组件需要的全局数据,映射为当前组件的computed计算属性
computed:{
//通过展开运算符映射成计算属性
...mapState(['count'])
}

Moutation

用于变更Store中的数据. 不能写异步的代码!!!

  1. 只能通过mutation变更Store数据,不可以直接操作Store中的数据
  2. 通过这种方式虽然操作起来比较繁琐,但是可以集中监控所有数据的变化

第一种调用方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
export default new Vuex.Store({
state: {
count: 0
},
//定义mutations
mutations: {
add(state) {
//变更状态
state.count += 1
}
},
//在相应的组件中调用
methods: {
addCount() {
//通过commit触发
this.$store.commit('add')
}
}

添加参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
export default new Vuex.Store({
state: {
count: 0
},
//定义mutations
mutations: {
addN(state,step) {
//变更状态
state.count += step
}
},
//在相应的组件中调用
methods: {
addCount() {
//通过commit触发
this.$store.commit('add',this.step)
}
}

第二种调用方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
    //定义mutations
mutations: {
add(state) {
//变更状态
state.count += 1
},
addN(state, step) {
state.count += step
},
sub(state) {
state.count -= 1
}
},

//在相应的组件中导入mapMutations
import { mapMutations } from 'vuex'
//在methods中通过...映射为当前组件的methods方法
methods: {
...mapMutations(['sub'])
}
//有参数的话 可以再定义一个函数,来调用this.subN(参数)

Action

我们刚才说过Mutation中不能执行异步操作,那么我们如果要用异步操作怎么办?这时候就需要用到action了

第一种方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//定义action
actions: {
addAsync(context) {
setTimeout(() => {
//不能直接修改state中的数据,必须通过Mutation中的函数
context.commit('add')
}, 1000);
}
},

//在相应组件中使用与Mutation类似,通过this.$store.dispatch
addAsync() {
this.$store.dispatch('addAsync')
}

第二种方式:

1
2
3
4
5
6
7
8
9
10
11
subAsync(context) {
setTimeout(() => {
context.commit('sub')
}, 1000);
}
//在相应的组件中导入mapMutations
import { mapActions } from 'vuex'
//在methods中通过...映射为当前组件的methods方法
methods: {
...mapActions(['sub'])
}

Getter

Getter 用于对Store 中的数据进行加工处理形成新的数据.

  1. Getter 可以对Store中已有数据加工处理之后形成新的数据,类似Vue的计算属性
  2. Store中数据发生变化,Getter的数据也跟着变化
1
2
3
4
5
6
7
8
9
10
11
12
13
//定义Getter
getters: {
showNum: state => {
return `当前最新的数字:${state.count}`
}
},
//当然调用也有两种
1.使用this.$store.getters.名称
2.导入 mapGetters
import { mapGetters } from 'vuex'
computed: {
...mapGetters(['showNum'])
},

Module

由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,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
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 的状态

项目结构

Vuex 并不限制你的代码结构。但是,它规定了一些需要遵守的规则:

  1. 应用层级的状态应该集中到单个 store 对象中。
  2. 提交 mutation 是更改状态的唯一方法,并且这个过程是同步的。
  3. 异步逻辑都应该封装到 action 里面。

只要你遵守以上规则,如何组织代码随你便。如果你的 store 文件太大,只需将 action、mutation 和 getter 分割到单独的文件。

对于大型应用,我们会希望把 Vuex 相关代码分割到模块中。下面是项目结构示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
├── index.html
├── main.js
├── api
│ └── ... # 抽取出API请求
├── components
│ ├── App.vue
│ └── ...
└── store
├── index.js # 我们组装模块并导出 store 的地方
├── actions.js # 根级别的 action
├── mutations.js # 根级别的 mutation
└── modules
├── cart.js # 购物车模块
└── products.js # 产品模块

参考官网文档:https://vuex.vuejs.org/zh/installation.html