vuex
什么是Vuex
vuex是一个专门为vue.js设计的集中式状态管理架构。将状态管理单独拎出来,应用统一的方式进行处理,在后期维护的过程中数据的修改和维护就变得简单而清晰了。Vuex采用和Redux类似的单向数据流的方式来管理数据。用户界面负责触发动作(Action)进而改变对应状态(State),从而反映到视图(View)上。如下图所示:

使用vuex
安装vuex
控制台 : npm install vuex --save 需要注意的是这里一定要加上 –save,因为你这个包我们在生产环境中是要使用的。
引入:
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(vuex);
入门小Demo
在 src 新建文件vuex(不是必须的),在里面新建文件store.js 文件引入vuex
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const state = { //声明问状态对象
count:1
};
const mutations= { //声明改变状态的方法
add(state){
state.count++;
},
reduce(state){
state.count--;
}
}
//用export default 封装代码,让外部可以引用。
export default new Vuex.Store({
state,
mutations
})
新建一个vue的模板,位置在components文件夹下,名字叫count.vue。在模板中我们引入我们刚建的store.js文件,并在模板中用{{$store.state.count}}输出count 的值。
<template> <div> <h2>{{msg}}</h2> <hr/> <h3>{{$store.state.count}}</h3> <p><button @click="$store.commit('add')">+</button></p> <p><button @click="$store.commit('reduce')">-</button></p> </div> </template> <script> import store from '@/vuex/store' export default{ data(){ return{ msg:'Hello Vuex', } }, store } </script>
在 路由里面引入这个组件
import Count from '@/components/Count'
{
path:'/count',
component: Count
}
核心的部分进行说明
State负责存储整个应用的状态数据,一般需要在使用的时候在跟节点注入store对象,(main.js)后期就可以使用this.$store.state直接获取状态
//store为实例化生成的
import store from './store'
new Vue({
el: '#app',
store,
render: h => h(App)
})
这个store可以理解为一个容器,包含着应用中的state等。实例化生成store的过程是:
const mutations = {...};
const actions = {...};
const state = {...};
Vuex.Store({
state,
actions,
mutation
});
后续在组件中使用的过程中,如果想要获取对应的状态你就可以直接使用this.$store.state获取,当然,也可以利用vuex提供的mapState辅助函数将state映射到计算属性中去,
//我是组件
import {mapState} from 'vuex'
export default {
computed: mapState({
count: state => state.count
})
}
这样直接就可以在组件中直接使用了。
state状态对象赋值给内部对象,也就是把stroe.js中的值,赋值给我们模板里data中的值。我们有三种赋值方式,我们一个一个来学习一下。
1.通过computed的计算属性直接赋值 (组件页面)
<script> import store from '@/vuex/store' export default{ data(){ return{ msg:'Hello Vuex', } }, computed:{ count(){ return this.$store.state.count } } } </script>
这里需要注意的是return this.$store.state.count这一句,一定要写this,要不你会找不到$store的。这种写法很好理解,但是写起来是比较麻烦的,
2.通过mapState的对象来赋值 //mapState 像当与映射
我们首先要用import引入mapState。 然后还在computed计算属性里写如下代码:
import {mapState} from 'vuex'; //注意mapState 写法
computed:mapState({
count:state=>state.count
})
//这里我们使用ES6的箭头函数来给count赋值。 等同于:
count:function(state){return state.count}
3.通过mapState的数组来赋值
这个算是最简单的写法了,在实际项目开发当中也经常这样使用。
computed:mapState(['count'])
Mutations 修改状态
利用它可以更改状态,本质就是用来处理数据的函数,其接收唯一参数值state。store.commit(mutationName)是用来触发一个mutation的方法。需要记住的是,定义的mutation必须是同步函数,否则devtool中的数据将可能出现问题,使状态改变变得难以跟踪。
const mutations = {
mutationName(state) {
//在这里改变state中的数据
}
}
在组件中触发:
//我是一个组件
export default {
methods: {
handleClick() {
this.$store.commit('mutationName')
}
}
}
或者使用辅助函数mapMutations直接将触发函数映射到methods上,这样就能在元素事件绑定上直接使用了。如:
import {mapMutations} from 'vuex'
//我是一个组件
export default {
methods: mapMutations([
'mutationName'
])
}
传值:在实际项目中我们常常需要在修改状态时传值 stroe.js里 add 加上一个参数n
const mutations={
add(state,n){
state.count+=n;
},
reduce(state){
state.count--;
}
}
在Count.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插件一样。
1.普通写法:
<script> import store from '@/vuex/store'; import {mapState} from 'vuex'; export default{ data(){ return{ msg:'Hello Vuex', } }, methods:{ add(){ this.$store.commit('add'); } }, computed:mapState(['count']) } </script>
2.引入mapMutations:
import {mapState, mapMutations} from 'vuex';
methods:mapMutations(['add','reduce']),
getters计算过滤操作
状态需要做二次处理时,可以使用getters。通过this.$store.getters.valueName对派生出来的状态进行访问。或者直接使用辅助函数mapGetters将其映射到本地计算属性中去。
const getters = {
strLength: state => state.aString.length
}
//上面的代码根据aString状态派生出了一个strLength状态
在组件中使用
import {mapGetters} from 'vuex'
export default {
computed: mapGetters([
'strLength'
])
}
比如我们现在要对store.js文件中的count进行一个计算属性的操作,就是在它输出前,给它加上100.
我们首先要在store.js里用const声明我们的getters属性。
const getters={
count:function(state){
return state.count+=10;
}
}
export default new Vuex.Store({
state,mutations ,getters
})
模板页对computed进行配置。在vue 的构造器里边只能有一个computed属性,如果你写多个,只有最后一个computed属性可用,所以要对上节课写的computed属性进行一个改造。改造时我们使用ES6中的展开运算符”…”。
computed:{
...mapState(["count"]),
count(){
return this.$store.getters.count;
}
},
用mapGetters简化模板写法:
import { mapState,mapMutations,mapGetters } from 'vuex';
//computed:mapState(['count']),
computed:{
...mapState(['count']),
...mapGetters(['count'])
},
actions异步修改状态
之前讲的Mutations功能基本一样,不同点是,actions是异步的改变state状态,而Mutations是同步改变状态。 异步简单来说就是互补干扰
在store.js中声明actions
const actions = {
addAction(context){
context.commit('add');
},
reduceAction({commit}){
commit('reduce')
}
}
//用export default 封装代码,让外部可以引用。
export default new Vuex.Store({
state,mutations ,getters,actions
})
- context:上下文对象,这里你可以理解称store本身。
- {commit}:直接把commit对象传递过来,可以让方法体逻辑和代码更清晰明了。
count.vue模板中编写代
<p> <button @click="addAction">+</button> <button @click="reduceAction">-</button> </p> import {mapState, mapMutations,mapGetters,mapActions} from 'vuex'; methods:{ ...mapMutations(['add','reduce']), ...mapActions(['addAction','reduceAction']), },
Plugins 外挂
插件就是一个钩子函数,在初始化store的时候引入即可。比较常用的是内置的logger插件,用于作为调试使用。
import createLogger from 'vuex/dist/logger'
const store = Vuex.Store({
...
plugins: [createLogger()]
})
module模块组
随着项目的复杂性增加,我们共享的状态越来越多,这时候我们就需要把我们状态的各种操作进行一个分组
在vuex/store.js中声明模块组,我们还是用我们的const常量的方法声明模块组。
const moduleA={
state,mutations,getters,actions
}
声明好后,我们需要修改原来 Vuex.Stroe里的值:
export default new Vuex.Store({
modules:{a:moduleA}
})
现在我们要在模板中使用count状态,要用插值的形式写入。
<h3>{{$store.state.a.count}}</h3> computed:{ count(){ return this.$store.state.a.count; } },

浙公网安备 33010602011771号