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 的解读算告一段落。
vuex 源码:深入 vuex 之辅助函数 mapState的更多相关文章
- vuex 源码分析(六) 辅助函数 详解
对于state.getter.mutation.action来说,如果每次使用的时候都用this.$store.state.this.$store.getter等引用,会比较麻烦,代码也重复和冗余,我 ...
- VueX源码分析(2)
VueX源码分析(2) 剩余内容 /module /plugins helpers.js store.js helpers要从底部开始分析比较好.也即先从辅助函数开始再分析那4个map函数mapSta ...
- VueX源码分析(5)
VueX源码分析(5) 最终也是最重要的store.js,该文件主要涉及的内容如下: Store类 genericSubscribe函数 resetStore函数 resetStoreVM函数 ins ...
- VueX源码分析(4)
VueX源码分析(4) /module store.js /module/module.js import { forEachValue } from '../util' // Base data s ...
- VueX源码分析(1)
VueX源码分析(1) 文件架构如下 /module /plugins helpers.js index.esm.js index.js store.js util.js util.js 先从最简单的 ...
- 逐行粒度的vuex源码分析
vuex源码分析 了解vuex 什么是vuex vuex是一个为vue进行统一状态管理的状态管理器,主要分为state, getters, mutations, actions几个部分,vue组件基于 ...
- Vuex 源码学习(一)
(一)Vuex 是什么? Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态, 并以相应的规则保证状态以一种可预测的方式发生变化. —— 来自 V ...
- vuex源码 安装依赖问题
今天下载vuex源码时 安装依赖出现以下问题 > chromedriver@2.32.3 install /Users/bao/Desktop/vue-store/vuex/node_modul ...
- VueX源码分析(3)
VueX源码分析(3) 还剩余 /module /plugins store.js /plugins/devtool.js const devtoolHook = typeof window !== ...
- 一张思维导图辅助你深入了解 Vue | Vue-Router | Vuex 源码架构
1.前言 本文内容讲解的内容:一张思维导图辅助你深入了解 Vue | Vue-Router | Vuex 源码架构. 项目地址:https://github.com/biaochenxuying/vu ...
随机推荐
- Could not complete request
Could not complete request com.alibaba.dubbo.rpc.RpcException: Forbid consumer 10.254.1.26 access se ...
- 合并ts到mp4
这个比较好用. copy /b d:\xxx\download_ts\* d:\xxx\download_ts\new.mp4 用python ffmpeg也可以,不过我合出来有卡顿或者掉声问题, ...
- 详解Django中六个常用的自定义装饰器
装饰器作用 decorator是当今最流行的设计模式之一,很多使用它的人并不知道它是一种设计模式.这种模式有什么特别之处? 有兴趣可以看看Python Wiki上例子,使用它可以很方便地修改对象行为, ...
- php canvas 前端JS压缩,获取图片二进制流数据并上传
<?php if(isset($_GET['upload']) && $_GET['upload'] == 'img'){ //二进制数据流 $data = file_get_c ...
- P3332 [ZJOI2013]K大数查询(线段树套线段树+标记永久化)
P3332 [ZJOI2013]K大数查询 权值线段树套区间线段树 把插入的值离散化一下开个线段树 蓝后每个节点开个线段树,维护一下每个数出现的区间和次数 为了防止MLE动态开点就好辣 重点是标记永久 ...
- 【python005-数据类型】
数据类型 一.字符串的相加是拼接,数字的相加是求和 二.python的数值类型:整形,浮点型,e记法,布尔类型 >>> 1.2e412000.0>>> 1.2e-4 ...
- topcoder srm 686 div1
problem1 link 左括号和右括号较少的一种不会大于20.假设左括号少.设$f[i][mask][k]$表示处理了前$i$个字符,其中留下的字符以$k$开头($k=0$表示'(',$k=1$表 ...
- Python3基础 list in/not in 判断一个变量是否在列表中存在
Python : 3.7.0 OS : Ubuntu 18.04.1 LTS IDE : PyCharm 2018.2.4 Conda ...
- P1337 [JSOI2004]平衡点 / 吊打XXX 模拟退火
链接 https://www.luogu.org/problemnew/show/P1337 思路 交了好多发,都是wrong 初始值取平均数就1A了 真的是玄学的算法 代码 // luogu-jud ...
- UVALive 7501 Business Cycle(二分)题解
题意:n个数,有一个起始值,按顺序从第一个开始不断循环取数,如果取完后相加小于0就变为0,最多取p个数,问你得到大于等于值g所需要的最小起始值为多少 思路:这题目爆long long爆的毫无准备,到处 ...