Vuex
概念
专门在Vue
中实现集中式状态(数据)管理的一个Vue
插件,对Vue
应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信。
使用场景
- 多个组件依赖于同一状态
- 来自不同组件的行为需要变更同一状态
工作原理
- Vue Components:Vue组件。HTML页面上,负责接收用户操作等交互行为,执行dispatch方法触发对应action进行回应。
- dispatch:操作行为触发方法,是唯一能执行action的方法。
- actions:操作行为处理模块。负责处理Vue Components接收到的所有交互行为。包含同步/异步操作,支持多个同名方法,按照注册的顺序依次触发。向后台API请求的操作就在这个模块中进行,包括触发其他action以及提交mutation的操作。该模块提供了Promise的封装,以支持action的链式触发。
- commit:状态改变提交操作方法。对mutation进行提交,是唯一能执行mutation的方法。
- mutations:状态改变操作方法。是Vuex修改state的唯一推荐方法,其他修改方式在严格模式下将会报错。该方法只能进行同步操作,且方法名只能全局唯一。操作之中会有一些hook暴露出来,以进行state的监控等。
- state:页面状态管理容器对象。集中存储Vue components中data对象的零散数据,全局唯一,以进行统一的状态管理。页面显示所需的数据从该对象中进行读取,利用Vue的细粒度数据响应机制来进行高效的状态更新。
- getters:state对象读取方法。图中没有单独列出该模块,应该被包含在了render中,Vue Components通过该方法读取全局state对象。
搭建Vuex环境
下载安装
vuex
npm i vuex
创建
src/store/index.js
该文件用于创建Vuex
中最为核心的store
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) //应用Vuex插件 const actions = {} //照顾actions-用于响应组件中的动作 const mutations = {} //准备mutations-用于操作数据(state) const state = {} //准备state-用于存储数据 //创建并暴露store export default new Vuex.Store({ actions, mutations, state, })
在
src/main.js
中创建vm
时传入store
配置项import Vue from 'vue' import Vuex from './App.vue' import store from './store' new Vue({ el:'#app', render:h => h(App), store, //配置项添加store beforeCreate(){ Vue.prototype.$bus = this } })
使用Vuex编写
Vuex的基本使用
初始化数据
state
,配置actions
、mutations
,操作文件store.js
组件中读取vuex中的数据
$store.state.数据
组件中修改vuex中的数据
$store.dispatch('action中的方法名',数据)
或$store.commit('mutations中的方法名',数据)
注意:若没有网络请求或其他业务逻辑,组件中也可越过
acitons
,即不写dispatch
,直接编写commit
src/store/index.js
该文件用于创建Vuex中最为核心的store
//该文件用于创建Vuex中最为核心的store
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex)
//准备actions——用于响应组件中的动作
const actions = {
jiaOdd(context,value){
console.log('actions中的jiaOdd被调用了')
if(context.state.sum % 2){
context.commit('JIA',value)
}
},
jiaWait(context,value){
console.log('actions中的jiaWait被调用了')
setTimeout(()=>{
context.commit('JIA',value)
},500)
}
}
//准备mutations——用于操作数据(state)
const mutations = {
JIA(state,value){
console.log('mutations中的JIA被调用了')
state.sum += value
},
JIAN(state,value){
console.log('mutations中的JIAN被调用了')
state.sum -= value
}
}
//准备state——用于存储数据
const state = {
sum:0 //当前的和
}
//创建并暴露store
export default new Vuex.Store({
actions,
mutations,
state,
})
src/components/Count.vue
<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, //用户选择的数字
}
},
methods: {
increment(){
this.$store.commit('JIA',this.n)
},
decrement(){
this.$store.commit('JIAN',this.n)
},
incrementOdd(){
this.$store.dispatch('jiaOdd',this.n)
},
incrementWait(){
this.$store.dispatch('jiaWait',this.n)
},
},
mounted() {
console.log('Count',this)
},
}
</script>
<style lang="css">
button{
margin-left: 5px;
}
</style>
getters配置项
概念:当
state
中的数据需要经过加工后再使用时,可以使用getters
加工,相当于全局计算属性。在
store.js
中追加getters
配置...... const getters = { bigSum(state){ return state.sum*10 } } //创建并暴露store export default new Vue.store({ ...... getters })
组件中读取数据
$store.getters.bigSum
四个map方法的使用
mapState方法:用于帮助映射
state
中的数据为计算属性<script> import {mapState,mapGetters} from 'vuex' export default { data() { return { } }, computed:{ //靠程序员自己亲自去写计算属性 /* sum(){ return this.$store.state.sum }, school(){ return this.$store.state.school }, subject(){ return this.$store.state.subject }, */ //借助mapState生成计算属性,从state中读取数据。(对象写法) // ...mapState({he:'sum',xuexiao:'school',xueke:'subject'}), //借助mapState生成计算属性,从state中读取数据。(数组写法) ...mapState(['sum','school','subject']), }, } </script>
mapGetters方法:用于帮助映射
getters
中的数据为计算属性<script> import {mapState,mapGetters} from 'vuex' export default { data() { return { } }, computed:{ /* bigSum(){ return this.$store.getters.bigSum }, */ //借助mapGetters生成计算属性,从getters中读取数据。(对象写法) // ...mapGetters({bigSum:'bigSum'}) //借助mapGetters生成计算属性,从getters中读取数据。(数组写法) ...mapGetters(['bigSum']) }, } </script>
mapActions方法:用于帮助生成
actions
对话的方法,即包含$store.dispatch(xxx)
的函数<script> import {mapState,mapGetters} from 'vuex' export default { data() { return { } }, methods: { //程序员亲自写方法 /* incrementOdd(){ this.$store.dispatch('jiaOdd',this.n) }, incrementWait(){ this.$store.dispatch('jiaWait',this.n) }, */ //借助mapActions生成对应的方法,方法中会调用dispatch去联系actions(对象写法) ...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'}) //借助mapActions生成对应的方法,方法中会调用dispatch去联系actions(数组写法) // ...mapActions(['jiaOdd','jiaWait']) }, } </script>
mapMutations方法:用于帮助生成与
mutations
对话的方法,即包含$store.commit(xxx)
的函数<script> import {mapState,mapGetters} from 'vuex' export default { data() { return { } }, methods: { //程序员亲自写方法 /* increment(){ this.$store.commit('JIA',this.n) }, decrement(){ this.$store.commit('JIAN',this.n) }, */ //借助mapMutations生成对应的方法,方法中会调用commit去联系mutations(对象写法) ...mapMutations({increment:'JIA',decrement:'JIAN'}), //借助mapMutations生成对应的方法,方法中会调用commit去联系mutations(数组写法) // ...mapMutations(['JIA','JIAN']), } </script>
注意:
mapActions
与mapMutations
使用时,若需要传递参数需要:在模板中绑定事件时传递好参数,否则参数是事件对象
模块化+命名空间
目的:让代码更好维护,让多种数据分类更加明确
修改
store.js
为了解决不同模块命名冲突的问题,将不同模块的
namespaced: true
,之后在不同页面中引入getters
actions
mutations
时,需要加上所属的模块名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 } })
开启命名空间后,组件中读取
state
数据// 方式一:自己直接读取 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: ...mapActions('countAbout', {increment: 'JIA', increment:'JIAN'})