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