React Core源码阅读
React 16.2.0 core部分模块解析。
React16版本中的对象包括Children, Component, PureComponent, unstable_AsyncComponent(还在测试中), Fragment, 以及从前就有的createElement, cloneElement, createFactory
先来看看Children
ReactChildren
这个模块中封装了了一些遍历子节点的方法,其中最重要的方法是
这个方法用迭代的方式来遍历子节点,子节点以数组嵌套或者迭代器嵌套的方式存储,该方法所要做的是根据数组或者迭代器来访问到以入参children为起始点的所有节点,节点指的是类型为ReactElement(Symbol)、数字(Symbol的替代形式)、字符串或者null的节点,在此节点上调用传入的callback方法,同时向callback方法中传入tranverseContext对象,当前遍历到的children,以及计算出的节点名称。
节点名称的计算公式为:’.’ + getComponentKey + ‘:’ + getComponentKey + ‘:’ + …
其中getComponentKey方法会返回component手动设置的key或者遍历到当前节点的index
tranverseContext是个可以设置的对象,包含以下五项:result, keyPrefix, func, context, count。其中result是一个数组,每到遍历到一个对象时,若有返回结果则会返回到此数组中,keyPrefix是个自定义的主键前缀,func会在遍历时就执行,执行的上下文为context,count用来记录当前遍历到的节点数量。
于是这个模块暴露出五个方法:
forEachChildren(children, forEachFunc, forEachContext),其中forEachFunc对应tranverseContext的func,forEachContext对应context,traverseAllChildrenImpl中的callback的调用为:forEachFunc.call(forEachContext, child, count),count为当前遍历到的次序值。
mapChildren(children, func, context),其中func对应tranverseContext的func,context对应context,不同的在于在traverseAllChildrenImpl中的callback与traverseContext的设置。traverseContext中传入一个空数组来记录mapChildren函数的返回值,而且传入的func需具有返回值,有效的返回值为ReactElement对象或者包含ReactElement的数组,调用与之前一致 mappedElement = func.call(context, child, count),count为当前遍历到的次序值。
countChildren(children, context),只是计数而已,调用和之前一致
toArray(children),将树形结构整理成数组形式,实现相当于简化的mapChildren
onlyChild(children),只是判断传入的是不是个ReactElement
可以引入一张我自己画的图来帮助理解:
再来看看ReactElement
ReactElement
Element和Component不是一回事,Element就是包含以下这几个属性的对象。
而createElement(type, config, children)就是一个通过输入的config来配置当前的ReactElement的工厂方法。一般是config中有什么就替换掉默认配置项,并赋值到props中,其中保留字[key, refs, self, source]不能被赋值,type对应的是element中的type,其中children在工厂方法中被赋值到props.children中去,并且无法直接更改(Object.freeze)。
再来看看Component
Component
Component具有四个自己的对象属性:updater由ReactDOM来实现
Component的原型中具有两个方法,setState和forceUpdate,均与updater的实现有关,
而PureComponent与AsyncComponent只是有一个静态属性的区别