一、前言
当我们的应用遇到多个组件共享状态时,会需要多个组件依赖于同一状态抑或是来自不同视图的行为需要变更同一状态。以前的解决办法:
a.将数据以及操作数据的行为都定义在父组件;
b.将数据以及操作数据的行为传递给需要的各个子组件(有可能需要多级传递)
传参的方法对于多层嵌套的组件将会非常繁琐,并且对于兄弟组件间的状态传递无能为力。在搭建下面页面时,你可能会对 vue 组件之间的通信感到崩溃 ,特别是非父子组件之间通信。此时就应该使用vuex,轻松可以搞定组件间通信问题。
在 vue 的世界里 vuex 是用来实现 mvvm 中关键的 vm 层(视图模型层),你甚至可以认为它就是 vue的奶妈,它总是可以为 vue的顺畅运行提供强大的支持
vuex基本概念
vuex是vue的状态管理工具,状态即数据。 状态管理就是管理vue中的数据
注意:
- 不是所有的场景都适用于vuex,只有在必要的时候才使用vuex,如果不必要,尽量别用
- 使用了vuex之后,会附加更多的框架中的概念进来,增加了项目的复杂度
vuex的优点
- vuex用于解决组件通讯的问题
- vuex可以集中的管理vue项目中用到的所有数据
为什么要使用vuex
- 在大型的项目中,组件通讯会变得很混乱,使用vuex可以统一管理组件之间的通讯
1.在了解vuex之前先了解下
什么是 MVVM
- 从图中可以看到,所谓的 MVVM 指的有框架中的三个部分 M(Model)、 V(View)、 VM(ViewModel)
- View:指的是视图层,我们一般通过html来实现它,它可以与 vm(视图模型)层 的数据数据进行双向绑定,同时也可以绑定 vm(视图模型) 层的事件处理方法。
- Model:指的是数据模型层,它类似于一个数据的仓库,在很多情况下我们是通过 api层来实现数据支持,它可以读取和处理从服务端传过来的数据,或者把特定的数据加工后送到服务端。
- ViewModel:指的是界面模型层,它包含了具体某个时刻界面状态的数据,更是可以把 M(模型)层的数据处理成合适界面显示结构,也可以把 V(视图)层生产出来的数据送给 M(模型)层。
vue组件提供的是一个 vm层的实现,在没有引入vuex的情况下,这会导致 vue 组件非常重、代码复用率低。
二、什么是Vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。这里的关键在于集中式存储管理。简单来说,对 vue 应用中多个组件的共享状态进行集中式的管理(读/写)
从图中可以看到 vuex 主要做了这么几件事
- 从 api (模型)层读入数据同时也可以把数据发送给模型层
- 把从模型层读取到的数据,通过 mutation写入到 state当中
- state会作为视图数据直接提供给 组件进行消费使用
- 组件可以把用户的行为(界面事件)输送给 actions
3.使用vuex
Vuex.Store里面包含这五个核心概念
我们将从vuex这五个核心概念一一分别介绍
一,state数据的共享
vuex中的数据源state,我们需要保存的数据就保存在这里,可以在页面通过 this.$store.state来获取我们定义的数据;state,用于存储数据和操作数据,相等于vue中的data
-
在vue-cli2中我们需要自己引入安装vuex
安装:npm install vuex --save -
在src目录下 新建state文件夹,新建index.js文件
-
在index.js文件中创建store 对象并暴露出去
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) //创建Store,用于存储数据和操作数据 const store = new Vuex.Store({ state: { city: '上海' //2. 指定state属性,用于提供数据 } }) //4.暴露store给main.js的vue根实例引入联系 export default store
//5.在组件中使用vuex中的数据
console.log(store.state.city)**
4.main.js中创建根实例时,传入store
5.然后子组件使用:这样在页面就可以显示store 对象的state的属性值“上海”
//获取城市名
{{this.$store.state.city}}
或者(用在组件中用计算属性返回this.$store.state.city为组件的属性city)
二.mutations的使用
修改vuex中的数据,必须在 mutations进行修改,不能直接修改
如果要修改state,需要在mutations的方法修改
mutations: {
// 添加一个方法// state:表示state对象,payload表示传进来的参数
mufun (state,payload) {
state.city = payload
}
}
2.在组件中
触发mutations
想要修改state,必须触发mutations提供的方法:"commit"*
无论是同步或者异步的actions想要触发调用mutations,都要通过commit的方法
通过commit从而转化触发mutations
this.$store.commit('mufun',“北京”)
2. 在Index.js中:
actions传给 mutations 使用ctx.commit(“定义 mutations的函数名”,参数)
vuex 利用辅助函数
mapState,mapMutations 辅助函数
一 .mapState:
-
在要使用的组件import { mapState } from ‘vuex’
-
mapState指将state数据映射到组件的计算属性中
computed: { ...mapState(['city']) }
html写法改为:{{this.city}}
二. mapMutations :
- 在要使用的组件import { mapState, mapMutations } from ‘vuex’
2., mapMutationss 是在组件的methods函数中并以数组方式映射的
三丶Getter使用
vuex中的getters,类似于实例中computed
getters的作用也是给vuex提供数据,但是这个数据是算出来的
1.在index.js
2.在组件中使用(跟state差不多,具体参考上面state用法)
3.mapGetters辅助函数使用方法
四.Action的使用
-
Action 提交的是 mutation,而不是直接变更状态。
-
actions类似于mutations,但是可以有异步的操作
-
actions是不能直接修改state数据,
-
修改state数据只有mutations
-
actions最终还是提交了mutations
-
ctx 上下文,代表了当前的store
从图中我们可以得知
- 从 api (模型)层读入数据同时也可以把数据发送给模型层
- 把从模型层读取到的数据,同步操作通过 mutation写入到 state当中
- state会作为视图数据直接提供给 组件进行消费使用
- 如为异步操作,则需要首先在组件中先dispatch(分发)action的函数, 然后再在action中commit函数(mutation函数),最后才mutation写入修好state中去
1.在组件中
2.在index.js
3.action赋值函数
引入并在在方法methods中使用
五丶Module的使用
- 由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
- 为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的
state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:
1.在index.js中
注意:
默认情况下,除了(state是带命名空间的模块私有的),而模块内部的 action、mutation 和 getter 是注册在全局命名空间的——这样使得多个模块能够对同一 mutation 或 action 作出响应。
可以通过添加 namespaced: true 的方式使其成为带命名空间的模块
2.在组件中辅助函数则需要在每个前面加上命名空间的名字
3.而不在辅助函数中则需要添加"user/"