什么是Vuex?
Vuex 是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间的数据共享.
![image-20200710180830043]()
如何没有vuex,我们大范围的传值的时候会十分麻烦,而有了vuex 我们只需要跟store相互就可以了
当然我们也不是所有的数据都需要放到vuex中,有一些组件私有的数据,我们没有必要把他放到vuex中,只有组件之间共享的数据,才有必要放到vuex中.
使用vuex统一管理状态的优点:
- 能够在vuex中几种管理共享的数据,易于开发和维护.
- 能够高效的实现组件之间的数据共享,提供开发效率.
- 存储在vuex中的数据都是响应式的,能够实时保持数据与页面的同步
Vuex的基本使用
安装vuex依赖包
1 2
| npm install vuex --save # 当然你也可以用 cnpm
|
导入vuex包
1 2 3 4
| import Vue from "vue"; import Vuex from "vuex";
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";
import store from "./store";
Vue.config.productionTip = false;
new Vue({ 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
| import {mapState} from 'vuex'
computed:{ ...mapState(['count']) }
|
Moutation
用于变更Store中的数据. 不能写异步的代码!!!
- 只能通过mutation变更Store数据,不可以直接操作Store中的数据
- 通过这种方式虽然操作起来比较繁琐,但是可以集中监控所有数据的变化
第一种调用方式
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: { add(state) { state.count += 1 } },
methods: { addCount() { 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: { addN(state,step) { state.count += step } },
methods: { addCount() { 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: { add(state) { state.count += 1 }, addN(state, step) { state.count += step }, sub(state) { state.count -= 1 } }, import { mapMutations } from 'vuex'
methods: { ...mapMutations(['sub']) }
|
Action
我们刚才说过Mutation中不能执行异步操作,那么我们如果要用异步操作怎么办?这时候就需要用到action了
第一种方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| actions: { addAsync(context) { setTimeout(() => { context.commit('add') }, 1000); } },
addAsync() { this.$store.dispatch('addAsync') }
|
第二种方式:
1 2 3 4 5 6 7 8 9 10 11
| subAsync(context) { setTimeout(() => { context.commit('sub') }, 1000); } import { mapActions } from 'vuex'
methods: { ...mapActions(['sub']) }
|
Getter
Getter 用于对Store 中的数据进行加工处理形成新的数据.
- Getter 可以对Store中已有数据加工处理之后形成新的数据,类似Vue的计算属性
- Store中数据发生变化,Getter的数据也跟着变化
1 2 3 4 5 6 7 8 9 10 11 12 13
| 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 store.state.b
|
项目结构
Vuex 并不限制你的代码结构。但是,它规定了一些需要遵守的规则:
- 应用层级的状态应该集中到单个 store 对象中。
- 提交 mutation 是更改状态的唯一方法,并且这个过程是同步的。
- 异步逻辑都应该封装到 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