小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金。
一,前言
上一篇,主要介绍了 Vuex 插件机制的实现,主要涉及以下几个点:
- Vuex 插件机制分析;
- Vuex 插件机制核心逻辑实现:plugins 插件注册、subscribe 订阅收集、replaceState 状态替换;
本篇,继续介绍 Vuex 辅助函数的实现;
二,辅助函数的介绍
1,辅助函数的作用
继续以之前的代码作为示例:
<template>
<div id="app">
<br> 根模块测试: <br>
商品数量: {{this.$store.state.num}} 个<br>
商品单价: 10 元<br>
订单金额: {{this.$store.getters.getPrice}} 元<br>
<button @click="$store.commit('changeNum',5)">同步更新:数量+5</button>
<button @click="$store.dispatch('changeNum',-5)">异步更新:数量-5</button>
<br> 子模块测试: <br>
A 模块-商品数量: {{this.$store.state.moduleA.num}} 个<br>
B 模块-商品数量: {{this.$store.state.moduleB.num}} 个<br>
C 模块-商品数量: {{this.$store.state.moduleA.moduleC.num}} 个<br>
<button @click="$store.commit('moduleA/changeNum',5)">A 模块-同步更新:数量+5</button>
<button @click="$store.commit('moduleB/changeNum',5)">B 模块-同步更新:数量+5</button>
<button @click="$store.commit('moduleA/moduleC/changeNum',5)">C 模块-同步更新:数量+5</button>
</div>
</template>
可以发现,在项目使用 Vuex 插件中 State、getter、mutation、action 时,需要通过类似 this.$store.state.num
这样一长串才可以实现,当模块层级较深就会变得更长;这种不太优雅的写法,也会影响到代码的可读性及后续运维;
所以,Vuex 插件提供了一系列辅助函数,用于简化和解决上边的问题;
2,辅助函数功能介绍
Vuex 提供了以下辅助函数:
- mapState:在组件的 computed 中使用;
- mapGetters:在组件的 computed 中使用;
- mapMutations:在组件的 methods 中使用;
- mapActios:在组件的 methods 中使用;
- createNamespacedHelpers:获取指定命名空间下的辅助函数;
三,Vuex 辅助函数的使用
使用官网 Vuex 插件提供的辅助函数对示例进行优化
1,辅助函数 mapState
<template>
<div id="app">
商品数量: {{num}} 个<br>
</div>
</template>
<script>
import { mapState } from "vuex";
export default {
computed: {
// 写法 1:
// ...mapState(["num"]),
// 写法 2:
...mapState({
num: state => state.num,
})
}
};
</script>
2,辅助函数 mapGetters
<template>
<div id="app">
订单金额: {{getPrice}} 元<br>
</div>
</template>
<script>
import { mapGetters } from "vuex";
export default {
computed: {
// 写法 1:
// ...mapGetters(["getPrice"]),
// 写法 2:
...mapGetters({
getPrice: "getPrice"
})
}
};
</script>
3,辅助函数 mapMutations
<template>
<div id="app">
商品数量: {{num}} 个<br>
商品单价: 10 元<br>
订单金额: {{getPrice}} 元<br>
<button @click="mutationChangeNum(5)">同步更新:数量+5</button>
</div>
</template>
<script>
import { mapState, mapMutations } from "vuex";
export default {
computed: {
...mapState(["num"]),
},
methods: {
// 写法 1:
// ...mapMutations(['changeNum']),
// 写法 2:
...mapMutations({
mutationChangeNum: 'changeNum',
})
}
};
</script>
4,辅助函数 mapActions
<template>
<div id="app">
<br> 根模块测试: <br>
商品数量: {{num}} 个<br>
商品单价: 10 元<br>
订单金额: {{getPrice}} 元<br>
<button @click="actionChangeNum(-5)">异步更新:数量-5</button>
</div>
</template>
<script>
import { mapState, mapActions } from "vuex";
export default {
computed: {
...mapState(["num"]),
},
methods: {
// 写法 1:
// ...mapActions(['changeNum'])
// 写法 2:
...mapActions({
actionChangeNum: 'changeNum'
})
}
};
</script>
5,辅助函数 createNamespacedHelpers
使用 createNamespacedHelpers 获取指定模块辅助函数,简化 Vuex 使用:
<template>
<div id="app">
A 模块-商品数量: {{numA}} 个<br>
C 模块-商品数量: {{numC}} 个<br>
<button @click="mutationAChangeNum(5)">A 模块-同步更新:数量+5</button>
<button @click="mutationCChangeNum(5)">C 模块-同步更新:数量+5</button>
</div>
</template>
<script>
import { mapState, mapMutations } from "vuex";
import { createNamespacedHelpers } from "vuex";
const { mapState: mapStateA, mapMutations:mapMutationsA } = createNamespacedHelpers('moduleA');
const { mapState: mapStateC, mapMutations:mapMutationsC } = createNamespacedHelpers("moduleA/moduleC");
export default {
computed: {
// 写法 1:
// ...mapState({
// numA: state => state.moduleA.num,
// numC: state => state.moduleC.num
// })
// 写法 2:
...mapStateA({
numA: state => state.num
}),
...mapStateC({
numC: state => state.num
})
},
methods: {
// 写法 1:
// ...mapMutations({
// mutationAChangeNum: 'moduleA/changeNum'
// }),
// // 写法 2:
...mapMutationsA({
mutationAChangeNum: 'changeNum'
}),
...mapMutationsC({
mutationCChangeNum: 'changeNum'
})
}
};
</script>
四,Vuex 辅助函数的实现
1,辅助函数逻辑分析
辅助函数 mapState、mapActions、mapMutations,通过将 vuex.store 中的属性映射到 vm 实例上,从而实现通过 vm 实例可以直接访问到 vuex.store 中的属性,简化 Vuex 操作;
2,mapState 实现
创建 mapState 方法:根据指定状态名,返回状态对象;
// src/vuex/ helpers.js
/**
* 根据指定状态名,返回状态对象
* @param {*} stateArr 指定需要返回的状态名
* @returns 状态对象
*/
export function mapState(stateArr) {
let obj = {};
for (let i = 0; i < stateArr.length; i++) {
let stateName = stateArr[i];
obj[stateName] = function () {
// 从 $store.state 中查找状态名
return this.$store.state[stateName]
}
}
return obj
}
Vuex 插件导出 mapState 方法:
// src/vuex/index.js
import { Store, install } from './store';
export default {
Store,
install
}
export * from './helpers';
其他辅助函数同理,后续补充;
export function mapGetters(gettersArr) {
let obj = {};
for (let i = 0; i < gettersArr.length; i++) {
let gettName = gettersArr[i];
obj[gettName] = function() {
return this.$store.getters[gettName]
}
}
return obj
}
五,结尾
本篇,主要介绍了 Vuex 辅助函数的实现,主要涉及以下几个点:
- Vuex 辅助函数作用和功能介绍;
- Vuex 辅助函数使用介绍;
- Vuex 辅助函数原理分析与代码实现;
至此,《Vuex 源码学习笔记》专栏完结,后续将会继续完善扩充;
准备开始下一个源码专栏~