前言

当一个组件要获取多个 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. Percona Server 5.6 安装TokuDB

    系统:Red Hat Enterprise Linux Server release 6.3 (Santiago) 数据库:Percona-Server-5.6.29-rel76.2-Linux.x8 ...

  2. 12: xlrd 处理Excel文件

    1.1 xlrd处理.xlsx 文件 1.xlrd常用方法 #!/usr/bin/python # coding:utf-8 # 用xlrd读取Excel文件基本用法 import sys impor ...

  3. shell 变量相关的命令

    变量="变量" readonly 变量名="变量"  表示设置该变量为只读变量 ,这个变量不能别改变 echo $变量名 set  显示本地所有的变量 unse ...

  4. CentOS7使用命令连接网络配置

    背景 在安装完CentOS7无桌面的情况下,无法使用桌面图标连接,如下图所示,这时我们需要在配置文件中配置网络连接信息. 步骤 查看ip地址:ifconfig PS:在未连接网络之前,我们是查看不到i ...

  5. 嵌入式电路中的BUCK VS LDO【转】

    本文转载自:http://blog.chinaunix.net/uid-25906157-id-4125916.html 作为一名FAE,才知硬件知识的匮乏.慢慢积累一点儿硬件知识吧!BUCK和LDO ...

  6. newcoder H肥猪(单调队列 / 线段树)题解

    题意: 小B来到了一个异世界,成为了肥猪之王. 在这个异世界,共有n种肥猪,编号分别为1,...,n. 小B希望集齐这n种肥猪. 召集肥猪有两种方式: 1. 花费a[i]的金币召唤一只编号为i的肥猪. ...

  7. FJUT3574 HOME_W的附加题(带权线段树)题解

    题意: 给定n个数a1,a2,a3,……an.和m次操作. 每次操作格式如下 x y k   表示将a[x]替换为y.并求替换后,前k小的数之和 思路:我们用带权线段树维护权值,这里就是维护i的个数n ...

  8. 程序重启RocketMQ消息重复消费

    最近在调试RocketMQ消息发送与消费的Demo时,发现一个问题:只要重启程序,RocketMQ消息就会重复消费. 那么这是什么原因导致的,又该如何解决呢? 经过一番排查,发现程序使用的Rocket ...

  9. c# 之系统环境安装

    在重装系统后,对一些原有软件进行了卸载,不知道是什么原因总是提示vs2015 需安装IE10,但是又碰到ie10的一些插件不适合此系统.网上介绍的vs修复没有任何作用 最后找到方法是:重装系统,然后不 ...

  10. $on在构造器外部添加事件(通过$emit进行外部调用)$once执行一次的事件(通过$emit进行外部调用)$off关闭事件

    $on 在构造器外部添加事件. $on接收两个参数,第一个参数是调用时的事件名称,第二个参数是一个匿名方法. 如果按钮在作用域外部,可以利用$emit来执行. html <div id=&quo ...