ReactElementValidator
ReactElementValidator模块,对外接口,内部调用ReactElement,用于创建、克隆ReactElement,或创建ReactElement的工厂函数,将校验组件的构造函数、使用propsType校验props、校验props.children是否ReactElement及多个子元素时包含key。
'use strict';
// 保存容器组件,即用户自定义组件的ReactCompositeComponent实例,添加ref引用的需要
// 同时用于提示用户加载的组件模块书写错误
var ReactCurrentOwner = require('./ReactCurrentOwner');
// ReactComponentTreeHook.getCurrentStackAddendum用于获取容器组价的信息
var ReactComponentTreeHook = require('./ReactComponentTreeHook');
var ReactElement = require('./ReactElement');
// 根据组件的propTypes静态属性校验props
var checkReactTypeSpec = require('./checkReactTypeSpec');
// 可否使用Object.defineProperty方法
var canDefineProperty = require('./canDefineProperty');
var getIteratorFn = require('./getIteratorFn');
// warning(condition,format) condition为否值,替换format中的"%s",并console.error警告
var warning = require('fbjs/lib/warning');
// 提示用户书写有错的组件构造函数名
function getDeclarationErrorAddendum() {
if (ReactCurrentOwner.current) {
var name = ReactCurrentOwner.current.getName();
if (name) {
return ' Check the render method of `' + name + '`.';
}
}
return '';
}
// 初次创建时警告,props.children未改变引起的更新不警告
var ownerHasKeyUseWarning = {};
// props.children的直系父组件信息
function getCurrentComponentErrorInfo(parentType) {
var info = getDeclarationErrorAddendum();
if (!info) {
var parentName = typeof parentType === 'string' ? parentType : parentType.displayName || parentType.name;
if (parentName) {
info = ' Check the top-level render call using <' + parentName + '>.';
}
}
return info;
}
// props.children单个值中含有多个ReactElement时,缺失key值警告直系父组件书写有误
function validateExplicitKey(element, parentType) {
if (!element._store || element._store.validated || element.key != null) {
return;
}
element._store.validated = true;
var memoizer = ownerHasKeyUseWarning.uniqueKey || (ownerHasKeyUseWarning.uniqueKey = {});
// 获取props.children的直系父组件信息
var currentComponentErrorInfo = getCurrentComponentErrorInfo(parentType);
if (memoizer[currentComponentErrorInfo]) {
return;
}
memoizer[currentComponentErrorInfo] = true;
var childOwner = '';
if (element && element._owner && element._owner !== ReactCurrentOwner.current) {
childOwner = ' It was passed a child from ' + element._owner.getName() + '.';
}
process.env.NODE_ENV !== 'production' ?
warning(false, 'Each child in an array or iterator should have a unique "key" prop.'
+ '%s%s See https://fb.me/react-warning-keys for more information.%s',
currentComponentErrorInfo, childOwner, ReactComponentTreeHook.getCurrentStackAddendum(element))
: void 0;
}
// 校验props.children的每项,单个值只校验是否ReactElement,多个值再校验是否存在key属性
function validateChildKeys(node, parentType) {
if (typeof node !== 'object') {
return;
}
// 数组形式
if (Array.isArray(node)) {
for (var i = 0; i < node.length; i++) {
var child = node[i];
if (ReactElement.isValidElement(child)) {
validateExplicitKey(child, parentType);
}
}
// 单个值
} else if (ReactElement.isValidElement(node)) {
if (node._store) {
node._store.validated = true;
}
// 迭代器形式???
} else if (node) {
var iteratorFn = getIteratorFn(node);
if (iteratorFn) {
if (iteratorFn !== node.entries) {
var iterator = iteratorFn.call(node);
var step;
while (!(step = iterator.next()).done) {
if (ReactElement.isValidElement(step.value)) {
validateExplicitKey(step.value, parentType);
}
}
}
}
}
}
// 根据组件的propTypes静态属性校验props,同时提示getDefaultProps只能用于React.createClass方法创建的组件
function validatePropTypes(element) {
var componentClass = element.type;
if (typeof componentClass !== 'function') {
return;
}
var name = componentClass.displayName || componentClass.name;
if (componentClass.propTypes) {
checkReactTypeSpec(componentClass.propTypes, element.props, 'prop', name, element, null);
}
if (typeof componentClass.getDefaultProps === 'function') {
process.env.NODE_ENV !== 'production' ?
warning(componentClass.getDefaultProps.isReactClassApproved,
'getDefaultProps is only used on classic React.createClass '
+ 'definitions. Use a static property named `defaultProps` instead.')
: void 0;
}
}
var ReactElementValidator = {
createElement: function (type, props, children) {
var validType = typeof type === 'string' || typeof type === 'function';
// 传参type用户自定义组件构造函数、或ReactDomComponent的类型字符串有误
if (!validType) {
if (typeof type !== 'function' && typeof type !== 'string') {
var info = '';
// 用于提示用户加载的组件模块可能尚未导出组件的构造函数
if (type === undefined || typeof type === 'object' && type !== null && Object.keys(type).length === 0) {
info += ' You likely forgot to export your component from the file ' + 'it\'s defined in.';
}
// 提示用户书写有错的组件构造函数名
info += getDeclarationErrorAddendum();
process.env.NODE_ENV !== 'production' ?
warning(false, 'React.createElement: type is invalid -- expected a string (for '
+ 'built-in components) or a class/function (for composite '
+ 'components) but got: %s.%s', type == null ? type : typeof type, info)
: void 0;
}
}
var element = ReactElement.createElement.apply(this, arguments);
if (element == null) {
return element;
}
// 校验props.children的每项,单个值只校验是否ReactElement,多个值再校验是否存在key属性
if (validType) {
for (var i = 2; i < arguments.length; i++) {
validateChildKeys(arguments[i], type);
}
}
// 根据组件的propTypes静态属性校验props,同时提示getDefaultProps只能用于React.createClass方法创建的组件
validatePropTypes(element);
return element;
},
createFactory: function (type) {
var validatedFactory = ReactElementValidator.createElement.bind(null, type);
validatedFactory.type = type;
// 提示自定义组件的构造函数、及ReactDomComponent的类型字符串不能获取
if (process.env.NODE_ENV !== 'production') {
if (canDefineProperty) {
Object.defineProperty(validatedFactory, 'type', {
enumerable: false,
get: function () {
process.env.NODE_ENV !== 'production' ?
warning(false, 'Factory.type is deprecated. Access the class directly '
+ 'before passing it to createFactory.')
: void 0;
Object.defineProperty(this, 'type', {
value: type
});
return type;
}
});
}
}
return validatedFactory;
},
cloneElement: function (element, props, children) {
var newElement = ReactElement.cloneElement.apply(this, arguments);
for (var i = 2; i < arguments.length; i++) {
validateChildKeys(arguments[i], newElement.type);
}
validatePropTypes(newElement);
return newElement;
}
};
module.exports = ReactElementValidator; 相关推荐
wikiwater 2020-10-27
阿斌Elements 2020-06-11
IdeaElements 2020-08-19
Sophiego 2020-08-16
Kakoola 2020-08-01
Kakoola 2020-07-29
ELEMENTS爱乐冬雨 2020-07-18
ELEMENTS爱乐小超 2020-07-04
ELEMENTS爱乐小超 2020-07-04
Kakoola 2020-06-28
Feastaw 2020-06-18
Wmeng0 2020-06-14
ELEMENTS爱乐冬雨 2020-06-14