vuex 源码:深入 vuex 之辅助函数 mapState
前言
当一个组件要获取多个 state 的时候,声明计算属性就会变得重复和冗余了。我们可以使用到辅助函数 mapState 来更快更简洁地生成计算属性。
所以我们得清楚,mapState 的作用就是帮我们把一个对象或数组里的值转化成计算属性的写法。同理,其它的辅助函数也是大同小异,只要知道了 mapState 的实现,其它的也基本都明白了。
注:本次阅读的是 vuex 的 2.0.0 版本,源码请戳 这里。
准备
解读前,我们需要熟悉一些方法的使用:
解读
先来 mapState 的使用方式:
import { mapState } from 'vuex'
export default {
computed: mapState([
// 映射 this.count 为 store.state.count
'count'
])
}
mapState 返回一个对象,我们知道以上的代码最后会变成这样:
import { mapState } from 'vuex'
export default {
computed: {
count () {
return this.$store.state.count
}
}
}
那么我们就来开始看看 mapState 做了什么处理。
还是从 vuex 的 APi 看起,打开 src/index.js 文件,最下面的代码中可以看到 vuex 暴露出的 mapState:
export default {
Store,
install,
mapState,
mapMutations,
mapGetters,
mapActions
}
定位后可以找到最前面的引入:
import { mapState, mapMutations, mapGetters, mapActions } from './helpers'
打开 src/helpers.js
文件,里面便有 mapState 的实现。
normalizeMap
想知道 mapStat 这个方法的实现,还得知道里面的 normalizeMap
这个方法的实现。定位找到 normalizeMap
方法:
function normalizeMap (map) {
return Array.isArray(map)
? map.map(key => ({ key, val: key }))
: Object.keys(map).map(key => ({ key, val: map[key] }))
}
这个方法主要是格式化 mapState 传进来的 states 参数。我们会知道 states 参数会是两种形式,一种是以数组的方式传入,另一种则是以对象的方法传入。
例如以下代码:
// 以数组的方式传入
mapState([
'count',
'add'
])
// 以对象的方法传入
mapState({
count: state => state.count,
countAlias: 'count'
})
经过 normalizeMap
方法处理后会变成这样:
// 以数组的方式传入
[
{
key: 'count',
val: 'count'
},
{
key: 'add',
val: 'add'
}
]
// 以对象的方法传入
[
{
key: count,
val: state => state.count
},
{
key: countAlias,
val: 'count'
}
]
mapState
知道了 normalizeMap
方法的实现,再回头看 mapState
方法的实现:
export function mapState (states) {
const res = {}
normalizeMap(states).forEach(({ key, val }) => {
res[key] = function mappedState () {
return typeof val === 'function'
? val.call(this, this.$store.state, this.$store.getters)
: this.$store.state[val]
}
})
return res
}
对刚刚 normalizeMap 格式化后返回的数组进行遍历,拼接一个符合 computed 的对象(需有返回值)。
对 normalizeMap 返回数组的对象里的 val 有两个判断。如果不是函数,直接查找 this.$store.state[val]
返回 state。如果是函数,则需要使用 call 将 val 这个函数的 this 指向 vue 实例,然后将 state 和 getters 传入,最后执行 val 函数。
val 函数
如果 val 是函数,可能有点难理解,举个例子,传入的参数可能是这样子的:
computed: mapState({
countPlusLocalState (state) {
return state.count + this.localCount
}
})
经过 normalizeMap
方法后返回的对象为:
[
{
key: 'countPlusLocalState',
val: function (state) {
return state.count + this.localCount
}
}
]
再经过 mapState 最后返回的 res 是。这里会将 val 函数执行一遍,将函数的返回值 return 出来。
{
countPlusLocalState: function mappedState () {
return this.$store.state.count + this.localCount
}
}
至此,mapState 的解读已经结束了。另外,mapState 还经常使用到 es6 的扩展运算符,这个不是 vuex 的实现,而是 es6 的一个新特性:
computed: {
localComputed () { /* ... */ },
// 使用对象展开运算符将此对象混入到外部对象中
...mapState({
// ...
})
}
例外需要注意,如果要使用 es6 的扩展运算符,还需要引入一个 babel 包:babel-plugin-transform-object-rest-spread。
总结
mapState 的代码不多,主要的功能就是将传入的数组或对象转成 computed 计算属性能够识别的代码。比较难理解的就是对象带有函数的返回值有点绕,多看几遍理解理解。
mapState 里面的代码实现非常的简洁精湛,主要用到了 js 的一些内置函数做处理,如果是我,估计会一直写 for 循环实现吧哈哈,从中收获到不少知识的。至此,vuex 的解读算告一段落。
相关文章
- 队列之王: Disruptor 原理、架构、源码 一文穿透
- Pipeline模式(netty源码死磕6)
- jquery技术揭秘静态工具函数源码重构
- 根据MATLAB的函数histeq()改写的运行在OpenCV1.x下的直方图规定化C++源码
- Spark 源码分析 -- RDD
- UCOSiii源码分析——os_task.c任务管理函数分析
- 爆肝了!阿里出版的这份 Spring Security 源码手册,狂揽 GitHub 榜首
- spring源码之BeanDefinitionScanner的底层源码详解
- Android Glide源码解读(一) : 主流程分析
- python tcp socket 源码分享
- python部分源码中方法只有pass占位符解释
- Nvidia GPU 入门教程之 07 TensorFlow MNiST GPU A100(教程含源码)
- SwiftUI 7GUIs编程基准之 04 定时器 掌握并发性、竞争性用户、信号交互、响应性(教程含源码)
- iOS 音频项目大全之iOS复调合成器支持AUV3和SF2 可连接蓝牙Bluetooth MIDI(教程含源码)
- SwiftUI ListItemTint 基础教程(含源码)
- Flutter 数据本地化之使用本地数据库和 Sqflite 构建 Flutter Colorful Notes 应用程序(教程含源码)
- SwiftUI内功 函数教程之默认参数值(教程含源码)
- Excel 函数教程之如何提取字符串部分内容特殊字符,六套完整解决方案 (教程含源码)
- SwiftUI 动画之图片360度旋转动画(教程含源码)
- 是否应该学习qt源码(碰到问题的时候,或者文档对函数描述不清楚的时候,可以看一下)
- 多目标遗传算法 ------ NSGA-II (部分源码解析) 目标函数值计算 eval.c
- 曹工说Redis源码(4)-- 通过redis server源码来理解 listen 函数中的 backlog 参数
- golang 实现程序运行时函数动态替换,举例说明动态注入和替换本地方法、系统库方法、第三方库方法,附完整源码实现
- 二.jQuery源码解析之构建jQuery之构建函数jQuery的7种用法