正式学习React(五) react-redux源码分析

磨刀不误砍柴工,咱先把react-redux里的工具函数分析一下:

源码点这里

 shallowEqual.js

 1 export default function shallowEqual(objA, objB) {
 2   if (objA === objB) {
 3     return true
 4   }
 5
 6   const keysA = Object.keys(objA)
 7   const keysB = Object.keys(objB)
 8
 9   if (keysA.length !== keysB.length) {
10     return false
11   }
12
13   // Test for A‘s keys different from B.
14   const hasOwn = Object.prototype.hasOwnProperty
15   for (let i = 0; i < keysA.length; i++) {
16     if (!hasOwn.call(objB, keysA[i]) ||
17         objA[keysA[i]] !== objB[keysA[i]]) {
18       return false
19     }
20   }
21
22   return true
23 }

这个几个api全都超级简单,我就不仔细讲解了,顾名思义,简单比较一下两个obj是否相等。

storeShape.js

1 import { PropTypes } from ‘react‘
2
3 export default PropTypes.shape({
4   subscribe: PropTypes.func.isRequired,
5   dispatch: PropTypes.func.isRequired,
6   getState: PropTypes.func.isRequired
7 })

顾名思义,强制性规定subscribe,dispacth,getState必须是func.

warning.js

 1 /**
 2  * Prints a warning in the console if it exists.
 3  *
 4  * @param {String} message The warning message.
 5  * @returns {void}
 6  */
 7 export default function warning(message) {
 8   /* eslint-disable no-console */
 9   if (typeof console !== ‘undefined‘ && typeof console.error === ‘function‘) {
10     console.error(message)
11   }
12   /* eslint-enable no-console */
13   try {
14     // This error was thrown as a convenience so that if you enable
15     // "break on all exceptions" in your console,
16     // it would pause the execution at this line.
17     throw new Error(message)
18     /* eslint-disable no-empty */
19   } catch (e) {}
20   /* eslint-enable no-empty */
21 }

就是用console.error 打印一下错误。

wrapActionCreators.js

1 import { bindActionCreators } from ‘redux‘
2
3 export default function wrapActionCreators(actionCreators) {
4   return dispatch => bindActionCreators(actionCreators, dispatch)
5 }

上一篇讲过 bindActionCreators


它返回的这个对象直接是以 我们定义单个actionCreator为key的,actionCreator函数为value的包装,并在actionCreator里挂着了dispacth的函数。使用的时候,直接调用同名key函数,就直接分发action了,不需要

我们手动的 dispacth(actionCreator(内容)), 直接key(内容) 就行了。

------------------------------------------------------工具全部介绍完毕-----是不是so easy??!!!------------------------------

 现在主角登场:

Provider.js

 1 import { Component, PropTypes, Children } from ‘react‘
 2 import storeShape from ‘../utils/storeShape‘
 3 import warning from ‘../utils/warning‘
 4
 5 let didWarnAboutReceivingStore = false
 6 function warnAboutReceivingStore() {
 7   if (didWarnAboutReceivingStore) {
 8     return
 9   }
10   didWarnAboutReceivingStore = true
11
12   warning(
13     ‘<Provider> does not support changing `store` on the fly. ‘ +
14     ‘It is most likely that you see this error because you updated to ‘ +
15     ‘Redux 2.x and React Redux 2.x which no longer hot reload reducers ‘ +
16     ‘automatically. See https://github.com/reactjs/react-redux/releases/‘ +
17     ‘tag/v2.0.0 for the migration instructions.‘
18   )
19 }
20
21 export default class Provider extends Component {

//关键部分,将this.store加到了context里,这里,子组件就可以通过context直接拿到store,不需要一级一级props传递下去。
22   getChildContext() {
23     return { store: this.store }
24   }
25
26   constructor(props, context) {
27     super(props, context)
28     this.store = props.store
29   }
30
31   render() {
32     return Children.only(this.props.children)
33   }
34 }
35
36 if (process.env.NODE_ENV !== ‘production‘) {
37   Provider.prototype.componentWillReceiveProps = function (nextProps) {
38     const { store } = this
39     const { store: nextStore } = nextProps
40
41     if (store !== nextStore) {
42       warnAboutReceivingStore()
43     }
44   }
45 }
46
47 Provider.propTypes = {     //要求我们的 store对象里面的3个必须是func
48   store: storeShape.isRequired,

//要求我们形如这种格式的 <Provider store={store}> <App/> </Provider> ,<App>必须是react的element,其实它还要求了只能是放单element的,这也是render这个本身限定的!!可以看上面的Children.Only()
49   children: PropTypes.element.isRequired
50 }    // 这个是和getChildContext一样,必须加的。

//访问context 的属性是需要通过 contextTypes 指定可访问的 元素一样。getChildContext 指定的传递给子组件的属性需要先通过 childContextTypes 来指定,不然会产生错误。
51 Provider.childContextTypes = {
52   store: storeShape.isRequired
53 }

关于context的用法,我在github上写了一个小demo。大家可以clone下来跑一跑,在我的代码基础上可以添加一下状态函数,看看react的状态生命周期的流程。点这里

对于上面的代码总结一下,Provider这个React 组件就是为了将Store挂在到Context中,然后我们写的APP 里就可以获得store了。

时间: 2024-10-07 05:30:08

正式学习React(五) react-redux源码分析的相关文章

Redux源码分析之compose

Redux源码分析之基本概念 Redux源码分析之createStore Redux源码分析之bindActionCreators Redux源码分析之combineReducers Redux源码分析之compose      解读之前先了准备一下基本知识 rest参数  形式为...变量名,用于获取函数的多余参数 ,该变量将多余的参数放入数组中, 只能是参数的最后一个. 扩展运算符 扩展运算符(spread)是三个点(...).它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序

Java显式锁学习总结之五:ReentrantReadWriteLock源码分析

概述 我们在介绍AbstractQueuedSynchronizer的时候介绍过,AQS支持独占式同步状态获取/释放.共享式同步状态获取/释放两种模式,对应的典型应用分别是ReentrantLock和Semaphore,AQS还可以混合两种模式使用,读写锁ReentrantReadWriteLock就是如此. 设想以下情景:我们在系统中有一个多线程访问的缓存,多个线程都可以对缓存进行读或写操作,但是读操作远远多于写操作,要求写操作要线程安全,且写操作执行完成要求对当前的所有读操作马上可见. 分析

WEKA学习——CSVLoader 实例训练 和 源码分析

简介: Weka支持多种数据导入方式,CSVLoader是能从csv文件加载数据集,也可以保存为arff格式文件.官方介绍文件:Converting CSV to ARFF ( http://weka.wikispaces.com/Converting+CSV+to+ARFF) CSVLoader加载文件,关键是对文件字段属性名称和属性的类型需要自己定义,这样才能得到满足自己需要的数据集. CSVLoader通过options设置,可以设置每一列的属性为Nominal,String,Date类型

Redis学习之intset整数集合源码分析

1.整数集合:整数的集合,升序排序,无重复元素 2.整数集合intset是集合键的底层实现之一,当一个集合只包含整数值的元素,并且这个集合的元素数量不多时,redis会使用整数集合作为集合键的底层实现 3.intset可通过属性自定义编码方式(int16_t/int32_t/int64_t) 4.当往inset插入新元素时,如果新元素的类型比inset的原编码类型长,那么要先对inset进行"升级"操作 5.升级操作:(不可逆操作) 1)根据新元素的类型,扩展intset底层数组的空间

正式学习React(四) ----Redux源码分析

今天看了下Redux的源码,竟然出奇的简单,好吧.简单翻译做下笔记: 喜欢的同学自己可以去github上看:点这里 createStore.js 1 import isPlainObject from 'lodash/isPlainObject' 2 import $$observable from 'symbol-observable' 3 4 /** 5 * These are private action types reserved by Redux. 6 * For any unkno

Android学习——涉及意识形态的LitePal源码分析

原创技术博客,请认准Azzssss的原文http://www.cnblogs.com/Azzssss/p/4147704.html. 这两天项目终于上线了,松了一口气,虽然还是很不稳定,见一步走一步吧.反正总算能抽出时间来写博客了.在项目中用到了LitePal,LitePal是什么鬼东西呢?它的Github主页是什么介绍的:“LitePal是一个开源的android库,允许开发者极其方便地去使用sqlite数据库.通过它,你甚至可以不写一行SQL语句来完成大部分的数据库操作,包括创建和更新表,c

JAVA入门学习:Java HashMap实例源码分析

本文来源:http://www.zretc.com/technologyDetail/464.html Entry是Map接口中的一个内部接口,它是实现键值对存储关键.在HashMap中,有Entry的实现类,叫做Entry.Entry类很简 单,里面包含key,value,由外部引入的hash,还有指向下一个Entry对象的引用,和数据结构中学的链表中的note节点很类似. 引言 HashMap在键值对存储中被经常使用,那么它到底是如何实现键值存储的呢? 一 Entry Entry是Map接口

Junit学习笔记(二): 源码分析(1)

使用ModelGoon画出来的UML图如下: 图中可以分析出: 1)Test是一个接口,TestSuit和TestCase,JUnit4TestAdapter,JUnit4TestCaseFacade都实现了Test类,这一种命令模式,只需要使用Test接口就可以使用到具体的类: 2)JUnit4TestAdapter是适配器, Filterable实现了对用例的过滤, Sortable实现了对用例的排序(按照字母进行排序): 3)TestResult实现了返回结果,TestFailure记录失

五)CodeIgniter源码分析之Router.php

1 <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); 2 3 // ------------------------------------------------------------------------ 4 5 /** 6 * Router Class 7 */ 8 class CI_Router { 9 10 /** 11 * Config class 12 */ 13 var $co

Junit学习笔记(二): 源码分析(2)-命令和组合模式

命令模式 命令模式的优点: 命令模式将调用操作的对象与如何实现该操作的对象解耦. 将命令当成一个头等对象,它们可以像一般对象那样进行操纵和扩展 可以将多个命令复合成一个命令,与Composite模式结合使用 增加新的命令很容易,隔离对现有类的影响 可以与备忘录模式配合,实现撤销功能. 命令模式图: 由此带来的好处:1.客户无需使用任何条件语句去判断测试的类型,可以用统一的方式调用测试和测试套件,解除了客户与具体测试子类的耦合2.如果要增加新的TestCase也很容易,实现Test接口即可,不会影