前言

当一个组件要获取多个 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的更多相关文章

  1. vuex 源码分析(六) 辅助函数 详解

    对于state.getter.mutation.action来说,如果每次使用的时候都用this.$store.state.this.$store.getter等引用,会比较麻烦,代码也重复和冗余,我 ...

  2. VueX源码分析(2)

    VueX源码分析(2) 剩余内容 /module /plugins helpers.js store.js helpers要从底部开始分析比较好.也即先从辅助函数开始再分析那4个map函数mapSta ...

  3. VueX源码分析(5)

    VueX源码分析(5) 最终也是最重要的store.js,该文件主要涉及的内容如下: Store类 genericSubscribe函数 resetStore函数 resetStoreVM函数 ins ...

  4. VueX源码分析(4)

    VueX源码分析(4) /module store.js /module/module.js import { forEachValue } from '../util' // Base data s ...

  5. VueX源码分析(1)

    VueX源码分析(1) 文件架构如下 /module /plugins helpers.js index.esm.js index.js store.js util.js util.js 先从最简单的 ...

  6. 逐行粒度的vuex源码分析

    vuex源码分析 了解vuex 什么是vuex vuex是一个为vue进行统一状态管理的状态管理器,主要分为state, getters, mutations, actions几个部分,vue组件基于 ...

  7. Vuex 源码学习(一)

    (一)Vuex 是什么? Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态, 并以相应的规则保证状态以一种可预测的方式发生变化. —— 来自 V ...

  8. vuex源码 安装依赖问题

    今天下载vuex源码时 安装依赖出现以下问题 > chromedriver@2.32.3 install /Users/bao/Desktop/vue-store/vuex/node_modul ...

  9. VueX源码分析(3)

    VueX源码分析(3) 还剩余 /module /plugins store.js /plugins/devtool.js const devtoolHook = typeof window !== ...

  10. 一张思维导图辅助你深入了解 Vue | Vue-Router | Vuex 源码架构

    1.前言 本文内容讲解的内容:一张思维导图辅助你深入了解 Vue | Vue-Router | Vuex 源码架构. 项目地址:https://github.com/biaochenxuying/vu ...

随机推荐

  1. Could not complete request

    Could not complete request com.alibaba.dubbo.rpc.RpcException: Forbid consumer 10.254.1.26 access se ...

  2. 合并ts到mp4

    这个比较好用. copy /b d:\xxx\download_ts\*   d:\xxx\download_ts\new.mp4 用python ffmpeg也可以,不过我合出来有卡顿或者掉声问题, ...

  3. 详解Django中六个常用的自定义装饰器

    装饰器作用 decorator是当今最流行的设计模式之一,很多使用它的人并不知道它是一种设计模式.这种模式有什么特别之处? 有兴趣可以看看Python Wiki上例子,使用它可以很方便地修改对象行为, ...

  4. php canvas 前端JS压缩,获取图片二进制流数据并上传

    <?php if(isset($_GET['upload']) && $_GET['upload'] == 'img'){ //二进制数据流 $data = file_get_c ...

  5. P3332 [ZJOI2013]K大数查询(线段树套线段树+标记永久化)

    P3332 [ZJOI2013]K大数查询 权值线段树套区间线段树 把插入的值离散化一下开个线段树 蓝后每个节点开个线段树,维护一下每个数出现的区间和次数 为了防止MLE动态开点就好辣 重点是标记永久 ...

  6. 【python005-数据类型】

    数据类型 一.字符串的相加是拼接,数字的相加是求和 二.python的数值类型:整形,浮点型,e记法,布尔类型 >>> 1.2e412000.0>>> 1.2e-4 ...

  7. topcoder srm 686 div1

    problem1 link 左括号和右括号较少的一种不会大于20.假设左括号少.设$f[i][mask][k]$表示处理了前$i$个字符,其中留下的字符以$k$开头($k=0$表示'(',$k=1$表 ...

  8. Python3基础 list in/not in 判断一个变量是否在列表中存在

             Python : 3.7.0          OS : Ubuntu 18.04.1 LTS         IDE : PyCharm 2018.2.4       Conda ...

  9. P1337 [JSOI2004]平衡点 / 吊打XXX 模拟退火

    链接 https://www.luogu.org/problemnew/show/P1337 思路 交了好多发,都是wrong 初始值取平均数就1A了 真的是玄学的算法 代码 // luogu-jud ...

  10. UVALive 7501 Business Cycle(二分)题解

    题意:n个数,有一个起始值,按顺序从第一个开始不断循环取数,如果取完后相加小于0就变为0,最多取p个数,问你得到大于等于值g所需要的最小起始值为多少 思路:这题目爆long long爆的毫无准备,到处 ...