react入口文件:
```
packages/react/src/React.js
```
**ReactElement文件**
`packages/react/src/ReactElement.js`
```
export function createElement(type, config, children) {
// 1:type是结点类型,如果是原生的节点,那么就是string,
如果是function component和class component就是组件,也可以是react原生的组件比如:
Fragment: REACT_FRAGMENT_TYPE,
StrictMode: REACT_STRICT_MODE_TYPE,
Suspense: REACT_SUSPENSE_TYPE,
2:config就是写在js标签上的所有的attr ,变成key:value
3:子标签
let propName;
// Reserved names are extracted
const props = {};
let key = null;
let ref = null;
let self = null;
let source = null;
if (config != null) {
if (hasValidRef(config)) {
ref = config.ref;
}
if (hasValidKey(config)) {
key = '' + config.key;
}
self = config.__self === undefined ? null : config.__self;
source = config.__source === undefined ? null : config.__source;
// Remaining properties are added to a new props object
for (propName in config) {
if (
hasOwnProperty.call(config, propName) &&
!RESERVED_PROPS.hasOwnProperty(propName)
) {
props[propName] = config[propName];
}
}
}
如果不是内嵌的props就放在新建的props中
// Children can be more than one argument, and those are transferred onto
// the newly allocated props object.
const childrenLength = arguments.length - 2; //后续的参数都认为是children
if (childrenLength === 1) {
props.children = children;
} else if (childrenLength > 1) {
const childArray = Array(childrenLength);
for (let i = 0; i < childrenLength; i++) {
childArray[i] = arguments[i + 2];
}
props.children = childArray;
}
// Resolve default props
//class Comp extends React.Component
//Comp.defaultProps = {value:1}
if (type && type.defaultProps) {
const defaultProps = type.defaultProps;
for (propName in defaultProps) {
if (props[propName] === undefined) {
props[propName] = defaultProps[propName];
}
}
}
return ReactElement(
type,
key,
ref,
self,
source,
ReactCurrentOwner.current,
props,
);
}
```
内嵌的
```
const RESERVED_PROPS = {
key: true,
ref: true,
__self: true,
__source: true,
};
```
```
const ReactElement = function(type, key, ref, self, source, owner, props) {
const element = {
// This tag allows us to uniquely identify this as a React Element
$$typeof: REACT_ELEMENT_TYPE,
// $$typeof:用来标示element是什么类型都的,
// 在写jsx代码的时候都是通过ReactElement创建的,
// 所有$$typeof:都是REACT_ELEMENT_TYPE,
// Built-in properties that belong on the element
type: type,
key: key,
ref: ref,
props: props,
// Record the component responsible for creating this element.
_owner: owner,
};
return element;
};
```
`ReactElement`通过`createElement`创建,调用该方法需要传入三个参数:
* type
* config
* children
`type`指代这个`ReactElement`的类型
* 字符串比如`div`,`p`代表原生DOM,称为`HostComponent`
* Class类型是我们继承自`Component`或者`PureComponent`的组件,称为`ClassComponent`
* 方法就是`functional Component`
* 原生提供的`Fragment`、`AsyncMode`等是Symbol,会被特殊处理
* TODO: 是否有其他的
从源码可以看出虽然创建的时候都是通过`config`传入的,但是`key`和`ref`不会跟其他`config`中的变量一起被处理,而是单独作为变量出现在`ReactElement`上。
在最后创建`ReactElement`我们看到了这么一个变量`$$typeof`,这是个啥呢,在这里可以看出来他是一个常量:`REACT_ELEMENT_TYPE`,但有一个特例:`ReactDOM.createPortal`的时候是`REACT_PORTAL_TYPE`,不过他不是通过`createElement`创建的,所以他应该也不属于`ReactElement`
`ReactElement`只是一个用来承载信息的容器,他会告诉后续的操作这个节点的以下信息:
1. `type`类型,用于判断如何创建节点
2. `key`和`ref`这些特殊信息
3. `props`新的属性内容
4. `$$typeof`用于确定是否属于`ReactElement`
这些信息对于后期构建应用的树结构是非常重要的,**而React通过提供这种类型的数据,来脱离平台的限制**
- 说明
- react源码
- 问答
- 慕课网视频
- 第二章:基础知识
- 001.ReactElement
- 002.react-component
- 003.ref
- 004.forwardRef
- 005.context
- 006.concurrentMode
- 007.supense和lazy
- 008.hooks
- 009.children
- 010.memo
- 011.others
- 第三章:react的更新
- 001.react-dom-render
- 第四章:Fiber Scheduler
- 第五章:各类组件的Update
- 第六章:完成节点任务
- 第七章:commitRoot
- 第八章:功能详解:基础
- 第九章:suspense and priority
- 第十章:功能详解:Hooks
- 001.基础知识
- 002.hook
- 003.RootFiber
- 004. hydrate
- react
- 高阶组件
- react基础
- Github面试题目