'解读 React 源码' .
来了来了
记录一些看书的时候,书上提到了但是对概念很模糊的内容。
当然惹,存在的问题就是书上讲解的 ReactJS 是 v15.0 的,目前是 v16.8。因此还要来做一些找不同。
export type
书上提到了 ReactNode 的类型,参考'packages/shared/ReactTypes.js'文件
差异在于书上(v15.0) 有三种类型 ReactElement 、ReactFragment 以及 ReactText
而现在(v16.8)的类型有如下
1 | export type ReactNode = |
看到这个代码的时候有两个疑问和一堆疑惑(关于这些是什么定义是什么
- export type 是什么 ?
- 为什么 = 之后直接跟的 | ?
对于第一问题,第一感觉是 ts 的语法,然后 google 一下发现真的是,用于重命名类型。
至于第二个问题,就是 ts 的语法啦。
对于 ts 有一些基础教程的阅读,但是对于 flow 的确实第一次接触。其次对于这些虚拟节点的类型,在以后实际看来了再回来瞅瞅。
createElement
在 v16.8 中 createElement() 和 ReactElement() 都在 'packages/src/ReactElement.js' 中了。
createElement() 的参数:
- type
- config
- children
参数对应的就是 jsx 编译后的内容,举个例子:
1 | <div style={{color: 'red'}}><span>demo</span><span>remix</span></div> |
config
先看源代码吧
这里和书上已经有较大的出入了
1 | if (config != null) { |
只有当 config 不为 null 时才会进行一些后续处理。
对于 ref 和 key 属性的处理调用了两个函数,对 ref 的处理函数如下,对于 ref 和 key 的处理一模一样。
1 | const hasOwnProperty = Object.prototype.hasOwnProperty; |
__DEV__ 是一个 global 变量,值是 'development' , 在'scripts/jest/setupEnviroment.js'中定义
接下来的 hasOwnProperty 比较好理解,就是判断这个 ref 对象是不是 config 对象本身的(而不是原型链上继承来的
但是 getter 这部分内容超出了理解。而书上对于 ref 和 key 的处理同对 self 和 source 的处理一致。
所以 Google 了一下
通過Ref屬性的取值器對象的isReactWarning屬性檢測是否含有合法的Ref,在開發環境下,如果這個props是react元素的props那麼獲取上面的ref就是不合法的,因爲在creatElement的時候已經調用了defineRefPropWarningGetter。生產環境下如果config.ref !== undefined,說明合法。
参考博客
简单来说,是因为 key 和 ref 的定义与其他 props 定义类似,而 key 和 ref 属性是不允许通过 props 获取的。开发环境需要检测 ref 是否合法,依据是当父组件元素的 ref 添加为子属性的 props.ref 时,getter.isReactWarning 为 true, 所以当这个 ref 是 class 组件的 props 时是不合法的,因此 return false。
在处理完 ref 、key 、self 、source 之后循环遍历把 config 中其余部分存入 props。
children
在之前的 jsx 编译 demo 中可以看到 children 可以有多个。
1 | const childrenLength = arguments.length - 2; |
当 children 只有一个的时候直接传给 props.children
而当 children 有多个的时候,传给 props.children 为一个数组。
默认 props 赋值
1 | // Resolve default props |
如果 type 的 defaultProps 存在则进行赋值操作。
ReactElement
这个内部方法,没有对外 export。
1 | const ReactElement = function(type, key, ref, self, source, owner, props) { |
返回 element ,
… 中进行的操作是在开发环境下 ,创建 self 、source 、store 属性,并且冻结 element 和 element.props
因为版本差异问题,在自己对于代码的阅读以及书本的讲解内容出入太大产生了一些压力,所以打算放弃参考书本内容,重新记录一份 React 源码的阅读。