Vuex实现任意组件的通信。
原理图:
其中数据存储在state对象中, 执行流程先调用dispatch方法调用actions中的方法,在actions调用mutations的方法提交操作,state中的数据变化,然后重新渲染。
使用步骤
- 安装
npm i vuex
特别注意:vue2中只能使用3版本,vue3中只能使用4版本。
- 使用
定义一个模块化的store tab.js
export default {
state : {
sum : 0,
},
actions : {
// context 想当于一个迷你版的store
jia(context, val){
context.commit("JIA", val);
}
},
mutations : {
// state 就是上面的数据
JIA(state,val) {
state.sum += val;
}
},
}
context中包含commit, dispatch, state, getters我们可以在actions中进一步调用其它的action及做一些其它的操作。
jia(context, val){
console.log(context)
// 调用其它actions
context.dispatch("print",val)
context.commit("JIA", val)
}
},
将模块化的store进行整合 index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
import tab from "@/store/tab";
// 创建实例
const store = new Vuex.Store({
modules : {
tab // 对象的简写形式,也可以写key value
}
})
export default store
在main.js中注册store
import store from "@/store";
new Vue({
store,
render: h => h(App),
}).$mount('#app')
在组件中使用
// 通过dispatch调用,联系的是actions中的动作
add() {
this.$store.dispatch("jia",3)
},
// 如果我们不需要action,也可以直接调用commit进行提交,注意commit是联系的mutations中的方法,mutations中的方法一般用大写定义。
add() {
this.$store.commit("JIA",3)
},
在页面上进行展示
<h3>{{this.$store.state.tab.sum}}</h3>
注:action中一般放异步请求,然后通过dispatch调用往vuex中存放数据。
// 和actions定义在一起,类似于计算属性,可以对state中的数据进行加工
getters : {
expandSum(state) {
return state.sum * 10
}
}
// 访问
this.$store.getters.expandSum
模块化后的更准确的引用:
// 引用数据
this.$store.state.home.sum
// 调用home模块下的add
this.$store.dispatch('home/add',data)
// 调用home模块下的ADD
this.$store.commit('home/ADD',data)
// home模块下的addr
this.$store.getters['home/addr']
注意:state和getters中的分类方式不一样,state是点调用就行了,但是getters中是’home/addr’
mapState 简化读数据操作
由于每次要访问数据前面都有很长的前缀,因此我们进行简化。
- 使用计算属性去简化
sum(){
return this.$store.state.sum
},
school(){
return this.$store.state.school
},
subject(){
return this.$store.state.subject
}
简化后:{{sum}}}
- 使用vuex 的mapState 来进行简化
当变量名与state中的变量名不同时,对象式写法
import {mapState} from 'vuex'
computed : {
// 这样就相当于自动生成了三个计算属性,并且生成的三个计算属性分别为he,xuexiao,xueke
...mapState({he:'sum',xuexiao:'school',xueke:'subject'})
},
在一个对象中将另一个对象的键值依次取出放到此对象中
let obj2 = {
name : "n",
age : 18
}
let obj = {
...obj2
}
若果变量名和state中的变量名相同,数组写法
computed : {
// 因为我们的state中的属性和计算属性相同不需要映射为别的名字直接数组写法即可
...mapState(['sum','school','subject'])
},
mapGetters 的用法和mapState一样,把getter中的属性映射为计算属性。
import {mapGetters} from 'vuex'
computed : {
...mapGetters({he:'bigSum',xuexiao:'lowSchool'})
},
- 模块化后的mapState的使用
const store = new Vuex.Store({
modules : {
home// 对象的简写形式,也可以写key value
}
})
export default store
- 方式1
// 这是把中state中的home都映射过来
...mapState(['home'])
// 由于是映射了home的state,使用的时候还需要在往下找属性
{{home.sum}}
- 方式2
第一个参数表示namespace, 需要开启namespace
home/index.js
const state = {}
const mutations = {}
const actions = {}
const getters = {}
export default {
namesapce:true,
state,
mutations,
actions,
getters
}
// 映射home模块下的sum,school, subject需要开启命名空间
...mapState('home',['sum','school','subject']),
// 使用的时候就可以直接使用
{{sum}}
关于mapMutations 与mapActions
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)
},
},
简写:
methods: {
// increment 和 JIA 进行关联 decrement 和 JIAN关联
...mapMutations({increment:'JIA',decrement:'JIAN'})
// 需要注意数组的写法需要Mutations里的方法和这个方法相同,使用的时候 @click="JIA(n)"
...mapMutations(['JIA','JIAN']),
...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
...mapActions(['jiaOdd','jiaWait'])
}
需要注意的是,我们自己写的时候知道加那个参数,但是自动生成的时候,是这种形式
increment(value){
this.$store.commit('JIA',value)
},
所以在使用的时候需要传参
<button @click="increment(n)">+</button>
<button @click="decrement(n)">-</button>
<button @click="incrementOdd(n)">当前求和为奇数再加</button>
<button @click="incrementWait(n)">等一等再加</button>
如果模块化后
// 第一个参数为namespace,同样需要开启namespace
//借助mapMutations生成对应的方法,方法中会调用commit去联系mutations(对象写法)
...mapMutations('home',{increment:'JIA',decrement:'JIAN'}),
//借助mapActions生成对应的方法,方法中会调用dispatch去联系actions(对象写法)
...mapActions('home',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
注:本文中的代码示例来源于尚硅谷视频教学。