目录
5.mapActions、mapMutations、mapState、mapGetters用法
1.下载vuex
此处注意如果使用的是vue@2版本,需要下载vuex@3,使用vue@3 下载vuex@4
npm install vuex@xxx (xxx为版本)
不使用对应版本会报错,或者导入并使用vuex后,new Vue时添加store属性添加不上
当Vue实例身上看到$store时就说明vuex安装好了
2. 准备store
src下准备一个store文件夹,在store文件夹中创建一个index.js文件,文件代码如下:
const actions = {}
const mutations = {}
const state = {}
export default new Vuex({
actions,
mutations,
state
})
在main.js中引用该文件,代码如下
import Vue from 'vue'
import App from './App.vue'
import vuex from "vuex"
Vue.config.productionTip = false
Vue.use(vuex)
import store from "./store"
const vm = new Vue({
render: h => h(App),
store
}).$mount('#app')
运行时会报错app.js:468 Uncaught ReferenceError: Vuex is not defined
原因:虽然将import store from "./store"写在了Vue.use(vuex)之后,但是vue先执行的是import语句,而在store的index.js中使用的new Vuex()
解决办法是,将vuex导入和使用语句放到store中,更正代码写法
store/index.js:
import Vue from "vue"
import Vuex from "vuex"
Vue.use(Vuex)
const actions = {}
const mutations = {}
const state = {}
export default new Vuex.Store({
actions,
mutations,
state,
})
main.js:
import Vue from 'vue'
import App from './App.vue'
import store from "./store"
Vue.config.productionTip = false
new Vue({
render: h => h(App),
store
}).$mount('#app')
3.应用举例
接下来简单实现一个数据+1的操作,此处注意this.$store.dispatch ===> actions
this.$store.commit ==> mutations
在业务逻辑直接是修改state数据的时候,可以直接调用commit
store/index.js
import Vue from "vue"
import Vuex from "vuex"
Vue.use(Vuex)
const actions = {
addSum(context,value){
console.log("actions:",context)
context.commit("ADDSUM",value)
//actions的方法是可以用dispatch继续调用actions中的方法
context.dispatch("demo1",value)
},
demo1(context,value){
console.log("actions的demo1")
}
}
const mutations = {
// 一般mutations中的名称用大写
ADDSUM(context,value){
console.log("mutations:",context)
context.sum += value
}
}
const state = {
sum:0
}
export default new Vuex.Store({
actions,
mutations,
state,
})
组件中
<template>
<div>
<h3>最终数据{{$store.state.sum}}</h3>
<button @click="addSum"> sum+1</button>
</div>
</template>
<script>
export default {
methods:{
addSum(){
this.$store.dispatch("addSum",1);
//此处也是可以直接调用mutations中的方法的
// this.$store.commit("ADDSUM",1)
}
}
}
</script>
下图中分别是actions和mutations方法中打印出来的context,可以看出actions中是可以获取到$store.state,按理说可以直接修改数据sum,就不用再commit去调用mutations中的ADDSUM方法修改数据,这么操作对于修改数据和视图来说没毛病,但是不推荐
因为开发者工具对接的是mutations而不是actions,在actions中修改数据,开发者工具是检测不到的
4.vuex实现原理
说原理就引用一下官网的图片
vue组件通过dispatch去调取actions中的方法, actions处理业务逻辑当需要修改state数据的时候,找到mutations,由mutations去实现数据修改,图中也是可以看到Devtools直接对接的是mutations,这就是为什么actions可以修改state数据却不推荐使用的原因了。
具体的内容可以查看vue官网https://cn.vuejs.org/
5.mapActions、mapMutations、mapState、mapGetters用法
这个都是vuex封装的方法,返回值是一个对象,分别对应:
mapActions-->actions --> dispatch
mapMutations-->mutation -- >commit
mapState--> state
mapGetters-->getters
state页面应用一般都是要this.$store.state.xxx 这种形式,可以通过mapState实现简单形式,如:
注意:mapActions与mapMutations使用时,若需要传递参数需要:在模板中绑定事件时传递好参数,否则参数是事件对象。
<template>
<div>
<!-- <h3>最终数据{{$store.state.sum}}</h3> -->
<h3>最终数据{{getSum}}</h3>
<h3>mapState形式:{{sum}}</h3>
<button @click="addSum(1)"> sum+1</button>
<hr/>
<h3>数据放大后处理 {{$store.getters.sumBig}}</h3>
<h3>mapGetters数据放大后处理 {{sumBig}}</h3>
</div>
</template>
<script>
import { mapState,mapGetters, mapActions } from 'vuex';
export default {
name: "TestStore",
methods:{
// addSum(){
// this.$store.dispatch("addSum",1);
// }
//此处和addSum函数效果相同,区别在于,如果用mapActions的时候addSum函数需要给传参
...mapActions({addSum:"addSum"})
},
computed:{
getSum(){
return this.$store.state.sum
},
getSumBig(){
return this.$store.getters.sumBig
},
//跟上面getSum计算属性一样可以达到获取sum的效果
...mapState({sum:"sum"}), //如果参数的key和value值名称相同,可以写成数组["sum"],
...mapGetters({sumBig:"sumBig"})
},
mounted() {
console.log(mapState({sum:"sum"}))
},
}
</script>
6.vuex的模块化
目的:让代码更好维护,让多种数据分类更加明确。实例代码
store/index.js 代码:
import Vue from "vue"
import Vuex from "vuex"
import number from "./number"
import moveOperate from "./moveOperate"
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
number,
moveOperate
}
})
number.js 代码:
export default {
namespaced: true,
actions: {
addSum(context,value){
console.log("actions:",context)
context.commit("ADDSUM",value)
}
},
mutations: {
ADDSUM(context,value){
console.log("mutations:",context)
context.sum += value
}
},
state: {
sum:0
},
getters: {
sumBig(state){
return state.sum*10
}
}
}
moveOperate.js代码
export default {
namespaced: true,
actions:{
moveForward(context,value){
if(value%2){
context.commit("GOSPEED", value)
}
}
},
mutations:{
GOSPEED(state,value){
state.speed += value
}
},
state:{
speed: 5,
},
getters:{
scaleSpeed(state){
return state.speed/3
}
},
}
vue组件代码:
<template>
<div>
<h2>number模块化简写形式</h2>
<p>getters:{{sumBig}}</p>
<p>总数 {{sum}}</p>
<button @click="addsum(1)">sum+1</button>
<button @click="a(1)">muttations修改数据</button>
<hr/>
<hr/>
<h2>move模块化直接引用方式</h2>
<p>getters:{{scaleSpeed}}</p>
<p>速度 {{speed}}</p>
<button @click="moveForward(1)">actions修改speed</button>
<button @click="commitSpeed(2)">直接使用mutations</button>
</div>
</template>
<script>
import {mapActions,mapGetters,mapMutations,mapState} from "vuex"
export default {
name: "StoreModel",
computed:{
...mapGetters("number",{sumBig: "sumBig"}),
...mapState("number",["sum"]),
// ~~~~~~~~~~~~~~~~~~~~speed
scaleSpeed(){
return this.$store.getters['moveOperate/scaleSpeed']
},
speed(){
//此处可以this.$store.state.moveOperate.speed,因为number.js中配置了namespaced:true,
return this.$store.state.moveOperate.speed ;
}
},
methods:{
...mapActions("number",{addsum: "addSum"}),
...mapMutations("number",{a:"ADDSUM"}),
//~~~~~~~~~~~~~~~~~speed
moveForward(val){
this.$store.dispatch("moveOperate/moveForward",val)
},
commitSpeed(val){
this.$store.commit("moveOperate/GOSPEED",val)
}
},
mounted(){
console.log(this.$store)
}
}
</script>
总结一下模块化:
1.每一个模块里面都可以有:
{
namespaced:true,//开启命名空间
actions:{},
mutations:{},
state:{},
getters:{}
}
2.state获取方式:
(1)this.$store.state.xxx.sum (xxx为模块名称)
(2)...mapState("xxx",{a:"sum"}) (a为自定义的名称,sum是模块里面state的属性名,xxx是模块名称)
3.getters获取方式
(1)this.$store.getters['xxx/sum']
(2)...mapGetters("xxx",{a:"sumBig"})
4.actions获取方法
(1)this.$store.dispatch("xxx/moveForward",val)
(2)...mapActions("xxx",{addsum: "addSum"})
5.mutations获取方法
(1)this.$store.commit("xxx/ADDSUM", val)
(2)...mapMutations("xxx",{b:"ADDSUM"})