Vuex ~ 初识
状态:data中的属性需要共享给其他vue组件使用的部分(即data中需要共用的属性)
1、初识vuex直接来个小demo
下面操作都是基于vue-cli,如果不了解先学习下vue-cli
利用npm包管理工具,进行安装 vuex。
npm install vuex --save
新建一个vuex文件夹(这个不是必须的),并在文件夹下新建store.js文件,文件中引入我们的vue和vuex。
import Vue from 'vue';
import Vuex from 'vuex';
使用我们vuex,引入之后用Vue.use进行引用。
Vue.use(Vuex);
通过以上操作,vuex就算引用成功了
直接来个demo,在vue-cli的src目录下新建一个文件夹vuex,并在此文件夹下新建一个store.js文件;直接上demo
现在我们store.js文件里增加一个常量对象 const state={ count:1 } 用export default 封装代码,让外部可以引用。 export default new Vuex.Store({ state }) 新建一个vue的模板,xxx.vue。在模板中我们引入我们刚建的store.js文件, 并在模板中用{{$store.state.count}}输出count 的值。 <template> <div> <h2>{{msg}}</h2> <hr/> <h3>{{$store.state.count}}</h3> </div> </template> <script> import store from '@/vuex/store' export default{ data(){ return{ msg:'Hello Vuex' } }, store //注意要先引用下 } </script> 在store.js文件中加入两个改变state的方法。 const mutations={ //改变state的数值 add(state){ state.count++; }, reduce(state){ state.count--; } } export default new Vuex.Store({ state, mutations }) 在xxx.vue模板中加入两个按钮,并调用mutations中的方法 <div> <button @click="$store.commit('add')">+</button> <button @click="$store.commit('reduce')">-</button> </div> 这样进行预览就可以实现对vuex中的count进行加减了
2.state访问状态对象
上面例子中 const state ,就是访问状态对象,也就是兄弟组件间的共享值。 下面是状态对象赋值给内部对象,也就是把stroe.js中的值,赋值给我们模板里data中的值 三种赋值方式: 一、通过computed的计算属性直接赋值 computed:{ count(){ return this.$store.state.count; } } 模板调用:{{count}} 缺点:当一个组件需要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余。 二、通过mapState的《对象》来赋值 import {mapState} from 'vuex'; 然后还在computed计算属性里写如下代码: computed:mapState({ count:state=>state.count }) 三、通过mapState的《数组》来赋值 computed:mapState(["count"])
3.Mutations修改state状态
1. mutations 相当于一个对象,对象里面放的是事件类型相对应的回调函数,作用就是进行状态更改;简单理解就相当于一个事件注册 2. $store.commit() //模板中调用mutations 里面的事件函数 传值:只需要在Mutations里再加上一个参数,并在commit的时候传递就就可以了 const mutations={ add(state,n){ state.count+=n; }, reduce(state){ state.count--; } } 在XXX.vue里修改按钮的commit( )方法传递的参数,我们传递10,意思就是每次加10. <p> <button @click="$store.commit('add',10)">+</button> <button @click="$store.commit('reduce')">-</button> </p> 模板获取Mutations方法 实际开发中我们也不喜欢看到$store.commit( )这样的方法出现,我们希望跟调用模板里的方法一样调用。 例如:@click=”reduce” 就和没引用vuex插件一样。 要达到这种写法,只需要简单的两部就可以了: 在模板XXX.vue里用import 引入我们的mapMutations: 1.在模板XXX.vue里用import 引入我们的mapMutations: import { mapState,mapMutations } from 'vuex'; 2.在模板的script标签里添加methods属性,并加入mapMutations methods:mapMutations([ 'add','reduce' ]), 3.通过上面两步后调用(注意额外参数直接写上) <button @click="add(10)">+</button>
4.getters计算过滤操作
getters从表面是获得的意思,可以把他看作在《 获取数据之前 》进行的一种再编辑(注意模板显示getters操作后的值) 相当于对数据的一个过滤和加工,可以把它看作store.js的计算属性(类似于computed) getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算 《1》基本用法: 首先要在store.js里用const声明我们的getters属性。 const getters = { count:function(state,getters){ return state.count +=getters.params_getter; }, params_getter:function(){ return 1000 } } 参数: state : getters : getters.xxx 来传递其他 getters 中的数据 写好了gettters之后,我们还需要在Vuex.Store()里引入 export default new Vuex.Store({ state,mutations,getters }) 在store.js里的配置算是完成了,我们需要到模板页对computed进行配置 在vue 的构造器里边只能有一个computed属性,如果你写多个,只有最后一个computed属性可用, 所以要对computed属性进行一个改造。 改造时我们使用ES6中的展开运算符”…”。 computed:{ ...mapState(["count"]), //相当于一个扩展 count(){ return this.$store.getters.count; } } 《2》用mapGetters简化模板写法: 都知道state和mutations都有map的引用方法把我们模板中的编码进行简化,我们的getters也是有的 首先用import引入我们的mapGetters import { mapState,mapMutations,mapGetters } from 'vuex'; 在computed属性中加入mapGetters ...mapGetters(["count"])
5.actions异步修改状态
actions和之前讲的Mutations功能基本一样 不同点是, 1.actions 提交的是 mutation,而不是直接变更状态。 2.actions是异步的改变state状态,而Mutations是同步改变状态。 在store.js中声明actions actions是可以调用Mutations里的方法的,在actions里调用add和reduce两个方法 以下是事件注册的两种方式: const actions ={ addAction(context){ context.commit('add',10) }, reduceAction({commit}){ //由于context 与 store 实例具有相同方法和属性,所以可以提交mutation commit('reduce') } } 在actions里写了两个方法addAction和reduceAction,在方法体里,我们都用commit调用了Mutations里边的方法。 context:上下文对象,这里你可以理解称store实例本身。 {commit}:直接把commit对象传递过来,可以让方法体逻辑和代码更清晰明了。 模板中的使用 <p> <button @click="addAction">+</button> <button @click="reduceAction">-</button> </p> 改造一下我们的methods方法,首先还是用扩展运算符把mapMutations和mapActions加入 methods:{ ...mapMutations([ 'add','reduce' ]), ...mapActions(['addAction','reduceAction']) } 用import把我们的mapActions引入才可以使用 import { mapState,mapMutations,mapGetters,mapActions } from 'vuex'; 增加异步检验 演示actions的异步功能,我们增加一个计时器(setTimeOut)延迟执行 setTimeOut(()=>{context.commit(reduce)},3000); console.log('我比reduce提前执行');
6.module模块组(状态管理器的模块组操作)
随着项目的复杂性增加,我们共享的状态越来越多,这时候我们就需要把我们状态的各种操作进行一个分组,分组后再进行按组编写。 声明模块组: 在vuex/store.js中声明模块组,我们还是用我们的const常量的方法声明模块组。代码如下: const moduleA = { state: { ... }, mutations: { ... }, actions: { ... }, getters: { ... } } const moduleB = { state: { ... }, mutations: { ... }, actions: { ... } } 声明好后,我们需要修改原来 Vuex.Stroe里的值: const store = new Vuex.Store({ modules: { a: moduleA, b: moduleB } }) store.state.a // -> moduleA 的状态 store.state.b // -> moduleB 的状态 在模板中使用: 现在我们要在模板中使用count状态,要用插值的形式写入 <h3>{{$store.state.a.count}}</h3> 如果想用简单的方法引入,还是要在我们的计算属性中rutrun我们的状态。写法如下: computed:{ count(){ return this.$store.state.a.count; } }