createElement
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) { // 验证是否有 Ref prop,如果有则取出 if (hasValidRef(config)) { ref = config.ref; } // 验证是否有 Key prop,如果有则取出,同时字符串化 if (hasValidKey(config)) { key = '' + config.key; } // 用于测试、debug、准确抛出错误用的信息 self = config.__self === undefined ? null : config.__self; source = config.__source === undefined ? null : config.__source; // 遍历 props,如果存在,并且并不与内部 props 冲突则合并到变量 props 中 // 简而言之,提取有用且有效的 props for (propName in config) { if ( hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName) ) { props[propName] = config[propName]; } } } // Children can be more than one argument, and those are transferred onto // the newly allocated props object. // 第三个参数开始,后面的参数都可以是 children,所以后面的参数有多少决定了 children 有多少 const childrenLength = arguments.length - 2; // 如果只有一个,则直接赋值 if (childrenLength === 1) { props.children = children; } else if (childrenLength > 1) { // 遍历入参,传到一个数组中,赋值到 children 中 const childArray = Array(childrenLength); for (let i = 0; i < childrenLength; i++) { childArray[i] = arguments[i + 2]; } props.children = childArray; } // 合并默认 props 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, );}
ReactElement
const ReactElement = function(type, key, ref, self, source, owner, props) { const element = { // This tag allows us to uniquely identify this as a React Element // 独一无二的表示,用于确认当前的元素是 react 的元素 $$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. // ReactCurrentOwner是一个对象,只有current一个属性,用于存储当前正在构建的Component所属的Component。 // ReactCurrentOwner.current主要在 react-dom 的ReactCompositeComponent中被赋值。 _owner: owner, }; return element;};
createFactory
// 用于生成快速生成某个组件的工厂函数的函数(真绕啊,汗export function createFactory(type) { const factory = createElement.bind(null, type); // Expose the type on the factory and the prototype so that it can be // easily accessed on elements. E.g. `<Foo />.type === Foo`. // This should not be named `constructor` since this may not be the function // that created the element, and it may not even be a constructor. // Legacy hook: remove it factory.type = type; return factory;}
cloneAndReplaceKey
// 克隆一个元素并重置其 key 值export function cloneAndReplaceKey(oldElement, newKey) { const newElement = ReactElement( oldElement.type, newKey, oldElement.ref, oldElement._self, oldElement._source, oldElement._owner, oldElement.props, ); return newElement;}
cloneElement
export function cloneElement(element, config, children) { // 类型校验 invariant( !(element === null || element === undefined), 'React.cloneElement(...): The argument must be a React element, but you passed %s.', element, ); let propName; // 浅拷贝被拷贝的元素的 props const props = Object.assign({}, element.props); // 获取被拷贝元素的 key,ref,_self,_source,_owner // Reserved names are extracted let key = element.key; let ref = element.ref; // Self is preserved since the owner is preserved. const self = element._self; // Source is preserved since cloneElement is unlikely to be targeted by a // transpiler, and the original source is probably a better indicator of the // true owner. const source = element._source; // Owner will be preserved, unless ref is overridden let owner = element._owner; // 获取新的元素配置,并覆盖被克隆元素传递下来的值 if (config != null) { if (hasValidRef(config)) { // Silently steal the ref from the parent. ref = config.ref; owner = ReactCurrentOwner.current; } if (hasValidKey(config)) { key = '' + config.key; } // Remaining properties override existing props let defaultProps; if (element.type && element.type.defaultProps) { defaultProps = element.type.defaultProps; } for (propName in config) { if ( hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName) ) { if (config[propName] === undefined && defaultProps !== undefined) { // Resolve default props props[propName] = defaultProps[propName]; } else { props[propName] = config[propName]; } } } } // Children can be more than one argument, and those are transferred onto // the newly allocated props object. const childrenLength = arguments.length - 2; 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; } // 创建元素对象 return ReactElement(element.type, key, ref, self, source, owner, props);}
isValidElement
// 通过元素的 $$typeof 判断该元素是不是 React 元素export function isValidElement(object) { return ( typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE );}