ReactElement.js
總體部分// packages/react/src/ReactElement.js
// 保留的 props
const RESERVED_PROPS = {
key: true,
ref: true,
__self: true,
__source: true,
};
const ReactElement = function(type, key, ref, self, source, owner, props) {
const element = {
// 此標記容許咱們將其惟一標識爲React元素
$$typeof: REACT_ELEMENT_TYPE,
// 屬於元素的內置屬性
type: type,
key: key,
ref: ref,
props: props,
// 記錄負責建立此元素的組件。
_owner: owner,
};
if (__DEV__) {/*...*/}
return element;
}
export function createElement(type, config, children) {
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];
}
}
}
const childrenLength = arguments.length - 2;
if( childrenLength === 1) {
props.children = children;
} else {
const childArray = Array(childrenLength);
for (let i = 0; i < childrenLength; i++) {
childArray[i] = arguments[i + 2];
}
if (__DEV__) { /*...*/ }
props.children = childArray;
}
return ReactElement(
type,
key,
ref,
self,
source,
ReactCurrentOwner.current,
props
);
}
複製代碼
1.ReactElement
是經過 createElement
函數建立;javascript
2.createElement
函數接收 3 個參數,分別是 type, config, children
, type 指的是 ReactElement
的類型;java
type 類型有react
div
或 p
等表明原生 DOM,稱爲 HostComponent
;Component
或 PureComponent
組件的稱爲 ClassComponent
;FunctionalComponent
;Fragment
、AsyncMode
等是 Symbol,會特殊處理;3.調用 ReactElement
,ReactElement
內部返回一個對象 element
;數組
config
邏輯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;
// 剩餘的屬性將添加到新的 props 對象中
for (propName in config) {
if(hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {
props[propName] = config[propName];
}
}
}
複製代碼
這段代碼函數
config
傳入的,ref
和 key
不會和 config
中的變量一塊兒被處理,而是單獨做爲變量出如今 ReactElement
上;ref
和 key
作了驗證(對於這種校驗方法無需內部實現,保持乾淨,也便於閱讀);config
把內建的幾個屬性(剔除原型鏈上的屬性和規定要剔除的屬性)丟到 props
中去;children
邏輯const childrenLength = arguments.length - 2;
if( childrenLength === 1) {
props.children = children;
} else {
const childArray = Array(childrenLength);
for (let i = 0; i < childrenLength; i++) {
childArray[i] = arguments[i + 2];
}
if (__DEV__) { /*...*/ }
props.children = childArray;
}
複製代碼
第一行能夠看出,取出第二個參數後的參數,而後判斷長度是否 > 1
:post
> 1
就表明有多個 children
,這個時候 props.children
會是一個數組, 因此後面在對 props.children
進行遍歷的時候須要注意它是不是數組,固然你也能夠利用 React.Children
中的 API,下文中也會對 React.Children
中的 API 進行講解;=== 1
就是一個對象;const ReactElement = function(type, key, ref, self, source, owner, props) {
const element = {
// 此標記容許咱們將其惟一標識爲React元素
$$type: REACT_ELEMENT_TYPE,
// 屬於元素的內置屬性
type: type,
key: key,
ref: ref,
props: props,
// 記錄負責建立此元素的組件。
_owner: owner,
};
if (__DEV__) {/*...*/}
return element;
}
複製代碼
核心就是經過 $$type
來識別這是個 ReactElement
,後會看到不少相似的類型。ui
注意:經過 JSX 寫的
<APP />
表明ReactElement
,APP
表明 React Component (組件)。spa