ReactElement

2023-11-02 22:39
文章标签 reactelement

本文主要是介绍ReactElement,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

ReactElement模块用于创建ReactElement。

特别的,当用户自定义组件的render方法中调用React.createElement方法时,将向子组件元素注入容器组件的ReactCompositeComponent,意义时使当前子组件元素添加为容器组件元素的ref引用成为可能。

 

'use strict';var _assign = require('object-assign');// 保存容器组件,即用户自定义组件的ReactCompositeComponent实例,添加ref引用的需要
var ReactCurrentOwner = require('./ReactCurrentOwner');// warning(condition,format) condition为否值,替换format中的"%s",并console.error警告
var warning = require('fbjs/lib/warning');// 可否使用Object.defineProperty方法
var canDefineProperty = require('./canDefineProperty');var hasOwnProperty = Object.prototype.hasOwnProperty;// symbal或0xeac7标识ReactElementType
var REACT_ELEMENT_TYPE = require('./ReactElementSymbol');var RESERVED_PROPS = {key: true,ref: true,__self: true,__source: true
};var specialPropKeyWarningShown, specialPropRefWarningShown;// 校验ref不是来自父组件的props.ref
function hasValidRef(config) {if (process.env.NODE_ENV !== 'production') {if (hasOwnProperty.call(config, 'ref')) {var getter = Object.getOwnPropertyDescriptor(config, 'ref').get;// 将父组件元素的props.ref添加为子组件元素的ref时,getter.isReactWarning为真if (getter && getter.isReactWarning) {return false;}}}return config.ref !== undefined;
}// 校验key不是来自父组件的props.key
function hasValidKey(config) {if (process.env.NODE_ENV !== 'production') {if (hasOwnProperty.call(config, 'key')) {var getter = Object.getOwnPropertyDescriptor(config, 'key').get;// 将父组件元素的props.key添加为子组件元素的key时,getter.isReactWarning为真if (getter && getter.isReactWarning) {return false;}}}return config.key !== undefined;
}// 不允许设置props的key属性
function defineKeyPropWarningGetter(props, displayName) {var warnAboutAccessingKey = function () {if (!specialPropKeyWarningShown) {specialPropKeyWarningShown = true;process.env.NODE_ENV !== 'production' ? warning(false, '%s: `key` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different '+ 'prop. (https://fb.me/react-special-props)', displayName) : void 0;}};warnAboutAccessingKey.isReactWarning = true;Object.defineProperty(props, 'key', {get: warnAboutAccessingKey,configurable: true});
}// 不允许设置props的ref属性
function defineRefPropWarningGetter(props, displayName) {var warnAboutAccessingRef = function () {if (!specialPropRefWarningShown) {specialPropRefWarningShown = true;process.env.NODE_ENV !== 'production' ? warning(false, '%s: `ref` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://fb.me/react-special-props)', displayName) : void 0;}};warnAboutAccessingRef.isReactWarning = true;Object.defineProperty(props, 'ref', {get: warnAboutAccessingRef,configurable: true});
}// 创建ReactElement,ReactElement.createElement用于转化处理配置项
// 参数type为用户自定义组件的构造函数,或者react封装的原生dom组件ReactDomElement的类型字符串,如"div"
// 参数key为ReactElement数组形式创建时添加的标识;同时,改变key值可用于销毁组件实例并重新生成实例
// 参数ref用于使当前ReactElement成为上层组件元素的ref引用
// 参数self、参数source调试时用,打印错误时区别于owner容器组件
// 参数owner顶级容器组件,在容器组件的render方法中调用React.createElement时注入
var ReactElement = function (type, key, ref, self, source, owner, props) {var element = {$$typeof: REACT_ELEMENT_TYPE,// symbal或0xeac7标识ReactElementtype: type,key: key,ref: ref,props: props,// 顶层容器组件实例,为将当前组件元素即子组件元素设置为顶层容器组件的ref引用,'react-dom'下ReactRef模块中使用_owner: owner};if (process.env.NODE_ENV !== 'production') {// element._store.validated用于存储子节点的校验值element._store = {};if (canDefineProperty) {Object.defineProperty(element._store, 'validated', {configurable: false,enumerable: false,writable: true,value: false});Object.defineProperty(element, '_self', {configurable: false,enumerable: false,writable: false,value: self});Object.defineProperty(element, '_source', {configurable: false,enumerable: false,writable: false,value: source});} else {element._store.validated = false;element._self = self;element._source = source;}if (Object.freeze) {Object.freeze(element.props);Object.freeze(element);}}return element;
};// 配置ReactElement元素的构造函数、props、props.children等属性,用于组件实例化时创建,以便组件实例化、挂载时进行渲染
// 参数type为用户自定义组件的构造函数,ReactComponent或ReactClass创建的组件,或普通函数返回ReactElement
//    或者字符串"div"等,表示react包装的原生dom组件ReactDomComponent
// 参数config包含子组件ref引用信息,及key标识数组中的某个ReactElement
//    以及__self属性,__source属性
//    以及组件元素props中的某些属性,即ref、key、__self、__source以外的属性
// 参数children添加为组件元素的props.children,组件实例化可按条件进行渲染
ReactElement.createElement = function (type, config, children) {var propName;var props = {};var key = null;var ref = null;var self = null;var source = null;if (config != null) {// 校验ref不是来自父组件的props.refif (hasValidRef(config)) {ref = config.ref;}// 校验key不是来自父组件的props.keyif (hasValidKey(config)) {key = '' + config.key;}self = config.__self === undefined ? null : config.__self;source = config.__source === undefined ? null : config.__source;// 将config中除ref、key、__self、__source以外的属性注入组件元素的props中for (propName in config) {if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {props[propName] = config[propName];}}}// 从第三个参数起作为组件元素的props.childrenvar 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 (process.env.NODE_ENV !== 'production') {if (Object.freeze) {Object.freeze(childArray);}}props.children = childArray;}// 将defaultProps注入props,前提是props中不存在值为真值的同名属性if (type && type.defaultProps) {var defaultProps = type.defaultProps;for (propName in defaultProps) {if (props[propName] === undefined) {props[propName] = defaultProps[propName];}}}// 不允许向props添加key、ref属性,props是ReactElement除外if (process.env.NODE_ENV !== 'production') {if (key || ref) {if (typeof props.$$typeof === 'undefined' || props.$$typeof !== REACT_ELEMENT_TYPE) {var displayName = typeof type === 'function' ? type.displayName || type.name || 'Unknown' : type;if (key) {defineKeyPropWarningGetter(props, displayName);}if (ref) {defineRefPropWarningGetter(props, displayName);}}}}// 创建ReactElement// ReactCurrentOwner.current为顶层容器组件实例,为将当前组件元素即子组件元素设置为顶层容器组件的ref引用,'react-dom'下ReactRef模块中使用// 即在用户自定义组件的render方法中调用React.createElement方法才使得ReactCurrentOwner.current为真值return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);
};// 创建组件元素的工厂函数,预先定义组件的构造函数type
ReactElement.createFactory = function (type) {var factory = ReactElement.createElement.bind(null, type);factory.type = type;return factory;
};// 替换原组件元素的key
ReactElement.cloneAndReplaceKey = function (oldElement, newKey) {var newElement = ReactElement(oldElement.type, newKey, oldElement.ref, oldElement._self, oldElement._source, oldElement._owner, oldElement.props);return newElement;
};// 以拷贝形式创建ReactElement
// 参数element待拷贝的ReactElement
// 参数config={ref,key,propName}重设新建组件元素的ref、key及部分props
// 参数children作为组件元素的props.children
ReactElement.cloneElement = function (element, config, children) {var propName;var props = _assign({}, element.props);var key = element.key;var ref = element.ref;var self = element._self;var source = element._source;var owner = element._owner;if (config != null) {// 重设ref,同时重设refif (hasValidRef(config)) {ref = config.ref;owner = ReactCurrentOwner.current;}// 重设keyif (hasValidKey(config)) {key = '' + config.key;}// 添加默认的defaultProps以及config中的props配置var 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) {props[propName] = defaultProps[propName];} else {props[propName] = config[propName];}}}}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];}props.children = childArray;}return ReactElement(element.type, key, ref, self, source, owner, props);
};// 通过$$typeof标识判断是否ReactElement
ReactElement.isValidElement = function (object) {return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;
};module.exports = ReactElement;

 

这篇关于ReactElement的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/333774

相关文章

React18原理: React核心对象之ReactElement对象和Fiber对象

React中的核心对象 在React应用中,有很多特定的对象或数据结构.了解这些内部的设计,可以更容易理解react运行原理列举从react启动到渲染过程出现频率较高,影响范围较大的对象,它们贯穿整个react运行时 如 ReactElement 对象如 Fiber 对象 其他过程的重要对象 如事件对象(位于react-dom/events保障react应用能够响应ui交互)如 ReactCon