createElement的流程圖解: html
一:React.createElement1.react 中的 jsx 代碼會被bable編譯成React.createElement, 因此在寫 jsx 代碼的時候 要引入React,不然會報錯react
<div className="first">第一次學習源碼丫~</div>
//像這樣的jsx會被編譯成
React.createElement('div', {
className: 'first'
}, '第一次學習源碼丫~')
複製代碼
createElement是建立並返回一個給定類型的ReactElement 元素,它有三個參數,其中type是必須的,config和children是可選的。 type:能夠是html的tagName,也能夠是ReactClass config:該標籤的屬性,這些屬性能夠用過this.props.xxx來取到 children:該元素的子節點數組
//源碼以下:
function createElement(type, config, children) {
var propName = void 0; //void 0 返回的就是undefined
// 提取保留名稱
var props = {};
var key = null;
var ref = null;
var self = null;
var source = null;
//對該標籤屬性的一些處理,若是屬性不爲空,就把特殊的屬性取出來 ref, key,__self, __source
if (config != null) {
if (hasValidRef(config)) {
ref = config.ref;
}
if (hasValidKey(config)) {
key = '' + config.key; //轉爲string類型
}
self = config.__self === undefined ? null : config.__self;
source = config.__source === undefined ? null : config.__source;
// Remaining properties are added to a new props object ( 剩餘的屬性被添加到一個新的props對象中)
for (propName in config) {
if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) { //hasOwnProperty 判斷括號中的屬性在不在自身中,不會檢查原型鏈
props[propName] = config[propName];
}
}
}
// Children can be more than one argument, and those are transferred onto the newly allocated props object.(children 能夠是多個參數,這些參數被轉移到新分配的props對象上)
//若是children是一個,就直接賦值給props.children
//若是不是一個,就吧它放在數組裏 賦值給props.children
var childrenLength = arguments.length - 2;
if (childrenLength === 1) {
props.children = children;
} else if (childrenLength > 1) {
var childArray = Array(childrenLength);
for (var i = 0; i < childrenLength; i++) {
childArray[i] = arguments[i + 2];
}
{
if (Object.freeze) {
Object.freeze(childArray);
}
}
props.children = childArray;
}
// Resolve default props 處理默認值defaultProps
if (type && type.defaultProps) {
var defaultProps = type.defaultProps;
for (propName in defaultProps) {
if (props[propName] === undefined) {
props[propName] = defaultProps[propName];
}
}
}
{
if (key || ref) {
var displayName = typeof type === 'function' ? type.displayName || type.name || 'Unknown' : type;
if (key) {
defineKeyPropWarningGetter(props, displayName);
}
if (ref) {
defineRefPropWarningGetter(props, displayName);
}
}
}
return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);
}
複製代碼
參考至: juejin.im/post/5cbae9…bash