vuex
专门在Vue中实现集中式状态(数据)管理的一个Vue插件
对Vue应用中的多个组件的共享状态进行集中式管理,也是一种组件之间的通信方式,适用于任意组件间通信
当多个组件依赖于同一状态或者来自不同组件的行为需要变更同一状态时使用
vuex中几大部件
state
vuex 管理的状态对象,它应该是唯一的
mutations
包含多个直接更新state 的方法(回调函数)的对象,由action 中的commit(‘mutation 名称’)触发
只能包含同步的代码, 不能写异步代码
actions
包含多个事件回调函数的对象,通过执行: commit()来触发mutation 的调用, 间接更新state
由组件中: $store.dispatch(‘action 名称’, data1) 触发
可以包含异步代码(定时器, ajax)
getters
不是必须的
当state中的数据需要经过加工之后再使用时,可以使用getters加工
包含多个计算属性(get)的对象
在组件中使用 $store.getters.xxx读取
const getters = {
mmm (state) {
return ...
}
}
mapState
用于帮助我们将state
中的数据映射为计算属性
...
import {mapState} from 'vuex'
...
computed: {
//借助mapState生成计算属性:sum、school、subject(对象写法)
...mapState({sum:'sum',school:'school',subject:'subject'}),
//借助mapState生成计算属性:sum、school、subject(数组写法)
...mapState(['sum','school','subject']),
},
...
mapGetters
用于帮助我们映射getters
中的数据为计算属性
使用方法类似于mapStates
...
import {mapGetters} from 'vuex'
...
computed: {
//借助mapGetters生成计算属性:bigSum(对象写法)
...mapGetters({bigSum:'bigSum'}),
//借助mapGetters生成计算属性:bigSum(数组写法)
...mapGetters(['bigSum'])
},
mapActions
用于帮助我们生成与actions
对话的方法,即:包含$store.dispatch(xxx)
的函数
...
import {mapActions} from 'vuex'
...
<button @click='incrementOdd(n)'>和为奇数时加</button>
<button @click='incrementWait(n)'>等一会再加</button>
...
methods:{
//靠mapActions生成:incrementOdd、incrementWait(对象形式)
...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
//靠mapActions生成:incrementOdd、incrementWait(数组形式)
...mapActions(['jiaOdd','jiaWait'])
}
mapMutations
用于帮助我们生成与mutations
对话的方法,即:包含$store.commit(xxx)
的函数
...
import {mapMutations} from 'vuex'
...
//注意,此时在元素标签内调用方法时,若在调用commit方法时需要传值,则需要带上括号传值
<button @click='increment(n)'>+</button>
<button @click='decrement(n)'>-</button>
...
methods:{
//靠mapActions生成:increment、decrement(对象形式)
...mapMutations({increment:'JIA',decrement:'JIAN'}),
//靠mapMutations生成:JIA、JIAN(对象形式)
...mapMutations(['JIA','JIAN']),
}
使用
先使用npm命令安装vuex,注意,vue2安装vuex3,vue3安装vuex4
然后在src目录下新增一个store目录,在其中添加一个index.js文件,用于创建Vue中最核心的store
index.js文件中需要引入vuex和vue,需要使用Vue.use()使用插件,需要定义actions,用于响应组件中的动作,需要定义mutations,用于操作数据,还需要定义state,用于存储定义,这三个均为对象,然后创建store,使用new Vuex.store(),其参数是一个配置对象,里面有actions、mutations、state,最后暴露store
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const actions={}
const mutations={}
const state={}
const store=new Vuex.Store({
actions,
mutations,
state,
})
export default store
然后回到main.js,引入store,并将其写在vue中
...
import store from './store/index'
new Vue({
el:'.root',
render:h=>h(App),
store:store,
})
在具体使用时,先调用使用dispatch调用actions中的方法,该方法使用commit调用mutations中的方法进行操作数据,有时候也可以跳过dispatch,直接使用commit调用mutations中的方法
实例:
main.js:
import Vue from 'vue'
import App from './App.vue'
import store from './store/index'
Vue.config.productionTip = false
new Vue({
el:'.root',
render:h=>h(App),
store:store,
})
index.js:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const actions={
// miniStore是一个精简版的store,value是使用dispatch调用时传入的参数
jia(miniStore,value){
miniStore.commit('JIA',value)
},
jian(miniStore,value){
miniStore.commit('JIAN',value)
},
jiaOdd(miniStore,value){
if(miniStore.state.sub%2!=0){
miniStore.commit('JIA',value)
}
},
jiaWait(miniStore,value){
setTimeout(()=>{
miniStore.commit('JIA',value)
},500)
}
}
const mutations={
// state是数据,value是使用commit调用时传入的参数
JIA(state,value){
state.sub+=value
},
JIAN(state,value){
state.sub-=value
}
}
const state={
sub:0
}
const store=new Vuex.Store({
actions,
mutations,
state,
})
export default store
app.vue:
<template>
<div>
<Count> </Count>
</div>
</template>
<script>
import Count from './components/Count.vue'
export default {
name:'App',
components:{Count}
}
</script>
count.vue
<template>
<div>
<!-- $store.state.sub用于读取store中的数据 -->
<h1>当前求和为:{{$store.state.sub}}</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 {
data(){
return{
n:1,
}
},
methods:{
increment(){
this.$store.dispatch('jia',this.n)
} ,
decrement(){
// 当逻辑中可以直接调用mutations中的方法时,可以直接使用commit
this.$store.commit('JIAN',this.n)
} ,
incrementOdd(){
this.$store.dispatch('jiaOdd',this.n)
} ,
incrementWait(){
this.$store.dispatch('jiaWait',this.n)
}
}
}
</script>
<style>
</style>
Vuex模块化
让代码更好维护,让多种数据分类更加明确
使用:
首先修改index.js里面的代码,将同一模块的数据及对应方法整理好
然后在创建store时,只需要将模块的名字放入modules配置中
const countAbout = {
namespaced:true,//开启命名空间
state:{x:1},
mutations: { ... },
actions: { ... },
getters: {
bigSum(state){
return state.sum * 10
}
}
}
const personAbout = {
namespaced:true,//开启命名空间
state:{ ... },
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
countAbout,
personAbout
}
})
组件中读取数据:
//personAbout是index.js中设置的模块名
//方式一:自己直接读取
this.$store.state.personAbout.list
//方式二:借助mapState读取:
...mapState('countAbout',['sum','school','subject']),
组件中读取getters数据:
//方式一:自己直接读取
this.$store.getters['personAbout/firstPersonName']
//方式二:借助mapGetters读取:
...mapGetters('countAbout',['bigSum'])
组件中调用dispatch:
//方式一:自己直接dispatch
this.$store.dispatch('personAbout/addPersonWang',person)
//方式二:借助mapActions:
...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
组件中调用commit:
//方式一:自己直接commit
this.$store.commit('personAbout/ADD_PERSON',person)
//方式二:借助mapMutations:
...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'}),