- 源码版本:React 16.2.0
React项目总览
- [项目地址](https://github.com/facebook/react/tree/v16.2.0)
- 使用的构建工具:yarn概览
react源码解读
- 先了解几个常量:ReactSymbols.js12345REACT_ELEMENT_TYPE //Symbol('react.element')REACT_FRAGMENT_TYPE //Symbol('react.fragment')REACT_CALL_TYPE //Symbol('react.call')REACT_RETURN_TYPE //Symbol('react.return')REACT_PORTAL_TYPE //Symbol('react.portal')
1.入口文件
|
|
2.React.js
|
|
3.ReactNoopUpdateQueue.js
|
|
4.ReactBaseClasses.js
1)返回用于构造组件的几个基类:Component,PureComponent,AsyncComponent
构造Component
1234567891011121314151617// 定义Component,有私有的props,context,refs,updater属性function Component(props, context, updater) {this.props = props;this.context = context;this.refs = emptyObject;this.updater = updater || ReactNoopUpdateQueue;}Component.prototype.isReactComponent = {};// this.state是不可变的,只能通过this.setState来更新// 使用this.setState更新state是批量更新// 所以调用this.setState后不会马上更新this.state,调用方法后马上访问this.state可能会得到旧的stateComponent.prototype.setState = function(partialState, callback) {this.updater.enqueueSetState(this, partialState, callback, 'setState');};Component.prototype.forceUpdate = function(callback) {this.updater.enqueueForceUpdate(this, callback, 'forceUpdate');};构造
PureComponent(AsyncComponent的构造和PureComponent同理),继承关系如图所示12345678910111213function PureComponent(props, context, updater) {this.props = props;this.context = context;this.refs = emptyObject;this.updater = updater || ReactNoopUpdateQueue;}function ComponentDummy() {}ComponentDummy.prototype = Component.prototype;var pureComponentPrototype = (PureComponent.prototype = new ComponentDummy());pureComponentPrototype.constructor = PureComponent;// Avoid an extra prototype jump for these methods.Object.assign(pureComponentPrototype, Component.prototype);pureComponentPrototype.isPureReactComponent = true;

* 本质上采用了 {% post_link 面向对象的程序设计之继承 寄生组合式继承 %} (通过构造函数继承属性,通过寄生式继承来继承方法)
* ComponentDummy:是一个中间类,它的prototype指向Component的原型对象
* ComponentDummy实例:通过new关键字创建,它的[[prototype]]指向Component的原型对象
* 扩展ComponentDummy实例:使其`constructor`指向`PureComponent`,并将`Component.prototype`上的属性赋给它(由于`Component.prototyp`的`constructor`属性是不可枚举的,所以不会覆盖之前的属性),并添加了`isPureReactComponent`属性
* 这样继承后的结果:当访问`setState`方法,会先看`PureComponent`的原型对象上是否有该方法,再去看`Component`的原型对象上是否有该方法。也就是说,当`Component`的原型对象发生改变时,不会影响到PureComponent;且这样继承后,声明的PureComponent实例的属性是通过PureComponent的构造函数构造的,而不是通过Component的构造函数。(总得来说这样继承拷贝了Component.prototype上的方法到PureComponent.prototype上,在之后对原型对象的操作时,将会互不影响。)
- 2)源码中对
setState的解释this.state应该被认为是不可变的,只能通过this.setState来更新- 由于使用
this.setState更新state是批量更新,所以调用this.setState不会马上更新this.state,调用方法后马上访问this.state将会得到旧的state
5.ReactChildren.js
几个功能函数
12getPooledTraverseContext(map, key, func, context) // 汇总上下文releaseTraverseContext(traverseContext) // 释放(release)上下文,将各个引用设为nullforEach、map、count、toArray都调用了同一个函数:traverseAllChildrenImpl- 如果Children为:
undefined,boolean,string,object(且$$typeof为特定值), 执行callback,并返回1 如果Children为Array:循环数组 计算节点数量,递归 调用callback
12345for (var i = 0; i < children.length; i++) {child = children[i];nextName = nextNamePrefix + getComponentKey(child, i);subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext); // 递归时,invokeCallback为真,会调用callback,并返回1}如果Children为Iterator(即可迭代对象):迭代对象 计算节点数量,递归 调用callback
- 如果Children为:
React.Children.only:判断是否只有一个Children1234567function onlyChild(children) {invariant(isValidElement(children), // 当chidlren.$$typeof为REACT_ELEMENT_TYPE才会为真'React.Children.only expected to receive a single React element child.',);return children;}
6.ReactElement.js
使用【工厂模式】创建
ReactElement对象1234567891011const ReactElement = function () {const element = {$$typeof: REACT_ELEMENT_TYPE,type: type,key: key,ref: ref,props: props,_owner: owner,}return element}提供了一系列方法:
createElement、createFactory、cloneAndReplaceKey、cloneElement、isValidElement