vuex
1)概念
专门在vue中实现集中式状态(数据)管理的一个Vue插件,对Vue应用中的多个组件的共享状态进行集中式的管理,也是一种组件间的通信的方式,且适用于任意组件间通信
2)什么时候使用Vuex
多个组件依赖于同一状态
来自不同组件的行为需要变更同一状态
3)vuex原理图
Vue Components ==》 Actions ==》 mutations ==》state ==》Vue Components
4)进行环境搭建
1)我们创建一个store文件,然后在里面创建 index.js,输入以下内容
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//引入Vuex
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
//准备actions---用于相应组件中的的动作
const actions = {}
//准备mutations---用于操作数据(state)
const mutations = {}
//准备state---用于存储数据
const state = {}
//创建store
export default new Vuex.Store({
actions:actions,
mutations:mutations,
state:state,
})
这里有一个Vuex的引入问题,本来我们是在main.js进行vuex的引入,但是因为其内部会自动将代码排序,然后导致代码出现错误,所以我们把vuex的引入放到index.js中,然后main.js只需要进行store的引入即可
5)制作一个小案例
对【求和案例纯vue代码】的改进
本来,在纯vue代码中,我们是将所有方法都配置在count.vue这个类中,但是vuex的情况,则是将这些操作的内容放置在【store】里面的【index.js】
大致如下
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//引入Vuex
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
//准备actions---用于相应组件中的的动作
const actions = {
jia(context,value){
//console.log(context,value)
context.commit('JIA',value)
},
jian(context,value){
context.commit('JIAN',value)
},
jiaOdd(context,value){
if(context.state.sum%2)
context.commit('JIAODD',value)
},
jiaWait(context,value){
setTimeout(()=>{
context.commit('JIAWAIT',value)
},500)
}
}
//准备mutations---用于操作数据(state)
const mutations = {
JIA(state,value){
console.log('mutations中的JIA被调用了',state,value)
state.sum += value
},
JIAN(state,value){
console.log('mutations中的JIAN被调用了',state,value)
state.sum -= value
},
JIAODD(state,value){
console.log('mutations中的JIAODD被调用了',state,value)
state.sum += value
},
JIAWAIT(state,value){
console.log('mutations中的JIAWAIT被调用了',state,value)
state.sum += value
}
}
//准备state---用于存储数据
const state = {
sum:0
}
//创建store
export default new Vuex.Store({
actions:actions,
mutations:mutations,
state:state,
})
然后,在count中,则输入对这些内容的一个引用
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<template> <div> <h1>当前求和为:{{$store.state.sum}}</h1> <select v-model.number="n"> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> </select> <button @click="increment">+</button> <button @click="decrement">-</button> <button @click="incrementOdd">当前求和为奇数再加</button> <button @click="incrementWait">等一等再加</button> </div> </template> <script> export default { name:'Count', data(){ return{ n:1, //用户选择的数组 //sum:0 将数据放置到vuex } }, methods:{ increment(){ this.$store.dispatch('jia',this.n) }, decrement(){ this.$store.dispatch('jian',this.n) }, incrementOdd(){ this.$store.dispatch('jiaOdd',this.n) }, incrementWait(){ this.$store.dispatch('jiaWait',this.n) }, }, mounted(){ console.log('Count',this) } } </script> <style> button{ margin-left: 5px; } </style>
6)对getters的一个使用
当我们想要对某个组件中的某个值(比如n)进行加工处理时,我们的基本做法是:在那个组件当中写上计算属性【computed】,然后在计算属性当中配置大致如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
computed:{
newn:{
get(){
return this.n*10;
}
}
}
但是,这种做法仅仅只能把这个值保存在当前组件当中,如果想要在其他组件中呈现加工后的值的话,那么我们可以选择vuex中的getters属性,进行如下的配置
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//准备getters---用于将state中的数据进行加工
const getters = {
bigSum(state){
return state.sum*10
}
}
然后,调用语句大致如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<h2>当前n的10倍为:{{$store.getters.bigSum}}</h2>
7)mapState
通过以上的内容的书写,可以发现,我们要调用vuex上面的属性时,会是这样的
即:想调用某个属性的时候,会出现这种要层层进入的情况
这种情况,vuex给了我们一个解决方法,即:mapState
我们给出如下例子:
我们在store下面的index.js配置一个【mingzi】属性
然后要在count组件里面查看该属性,那么我们就得写 $store.state.mingzi
假如我们不想写这么长,可以引入mapState
步骤为
1)引入
import {mapState} from 'vuex'
2)使用
...mapState({name:'mingzi'}), //对象写法,可以将mingzi改为其他内容进行映射
...mapState(['mingzi']), //数组写法,只能按我们在state中的内容进行呈现
数组的原理图如下:
一个mingzi对应两个地方的定义
3)调用
8)mapGetters
大致情况如上,步骤如下
1)引入
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import {mapState,mapGetters} from 'vuex'
2)使用
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
...mapGetters(['bigSum']),
3)调用
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<h2>当前n的10倍为:{{bigSum}}</h2>
9)MapActions方法
10)mapMutations方法
11)多组件共享数据的实现
1)假如我们没有用vuex的话,在各个组件内自个定义的数据,是很难数据共享的,而vuex将数据定义在某个特定地方【我的是在目录store的index.js之下】,所以我们可以用vuex来进行数据间的交互
我们的两个组件如下
count组件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<template> <div> <h1>当前求和为:{{$store.state.sum}}</h1> <h2>当前n的10倍为:{{bigSum}}</h2> <h3>{{name}}</h3> <select v-model.number="n"> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> </select> <button @click="increment">+</button> <button @click="decrement">-</button> <button @click="incrementOdd">当前求和为奇数再加</button> <button @click="incrementWait">等一等再加</button> <h3>人员列表的总人数为:{{$store.state.personList.length}}</h3> </div> </template> <script> import {mapState,mapGetters} from 'vuex' export default { name:'Count', data(){ return{ n:1, //用户选择的数组 //sum:0 将数据放置到vuex } }, methods:{ increment(){ this.$store.dispatch('jia',this.n) }, decrement(){ this.$store.dispatch('jian',this.n) }, incrementOdd(){ this.$store.dispatch('jiaOdd',this.n) }, incrementWait(){ this.$store.dispatch('jiaWait',this.n) }, }, computed:{ /* newn:{ get(){ return this.n*10; } } */ /* mingzi(){ return this.$store.state.mingzi }, */ ...mapState({name:'mingzi'}), //对象写法,可以将mingzi改为其他内容进行映射 //...mapState(['mingzi']), //数组写法,只能按我们在state中的内容进行呈现 ...mapGetters(['bigSum']), bigSum(){ return this.$store.getters.bigSum } }, mounted(){ const x = mapState({mingzi:'mingzi'}) console.log(x) }, } </script> <style> button{ margin-left: 5px; } </style>
createPerson组件如下
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<template> <div> <input type="text" placeholder="请输入名字" v-model="name"> <button @click="add">添加</button> <ul> <li v-for="p in $store.state.personList" :key="p.id">{{p.name}}</li> </ul> <h3>{{$store.state.mingzi}}</h3> </div> </template> <script> export default { name:'Person', data(){ return{ name:'' } }, computed:{ personList(){ return this.$store.state.personList } }, methods:{ add(){ this.$store.state.countId++ const personObj = {id:this.$store.state.countId,name:this.name} this.$store.commit('ADD_PERSON',personObj) this.name='' } } } </script> <style> </style>
App组件如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<template> <div> <Count></Count> <h3>fgdfsgdfgf</h3> <createPerson></createPerson> </div> </template> <script> import Count from './components/count.vue' import createPerson from './components/createPerson.vue' export default { name:'App', components:{Count,createPerson}, mounted(){ console.log('App',this) } } </script> <style> </style>
然后,想要进行组件间的通信,我们可以这样调用