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面試題目