react-element
Version:
94 lines (74 loc) • 2.55 kB
JavaScript
import cx from 'classnames';
import PropTypes from 'prop-types';
import { createElement, isValidElement, cloneElement, Children } from 'react';
function _objectWithoutPropertiesLoose(source, excluded) {
if (source == null) return {};
var target = {};
var sourceKeys = Object.keys(source);
var key, i;
for (i = 0; i < sourceKeys.length; i++) {
key = sourceKeys[i];
if (excluded.indexOf(key) >= 0) continue;
target[key] = source[key];
}
return target;
}
var reEvent = /^on\w+$/;
var isFunction = function isFunction(f) {
return typeof f === 'function';
}; // 属性后定义后覆盖(除了 class 始终拼接起来),处理函数先定义先执行
var mergeProps = function mergeProps(destProps, srcProps) {
var className = cx(srcProps.className, destProps.className);
var resultProps = Object.assign({}, destProps, srcProps, className && {
className: className
}); // keep event handlers
Object.keys(destProps).forEach(function (key) {
var destHandler = destProps[key];
var srcHandler = srcProps[key];
if (isFunction(destHandler) && isFunction(srcHandler) && reEvent.test(key)) {
resultProps[key] = function () {
destHandler.apply(this, arguments);
srcHandler.apply(this, arguments);
};
}
});
return resultProps;
};
/**
* 元素替换
*
* // 标签替换
* <Element component='span'>text</Element>
* // 构造函数替换
* <Element component={Header}>text</Element>
* // 实例替换
* <Element component={<Link to='/' />}>text</Element>
*/
var Element = function Element(_ref) {
var component = _ref.component,
children = _ref.children,
ownProps = _objectWithoutPropertiesLoose(_ref, ["component", "children"]);
var type = typeof component;
if (type === 'string') {
if (ownProps.onRef) {
ownProps.ref = ownProps.onRef;
delete ownProps.onRef;
}
return createElement(component, ownProps, children);
} else if (type === 'function') {
return createElement(component, ownProps, children);
} else if (isValidElement(component)) {
var childProps = mergeProps(component.props, ownProps);
if (children) {
return cloneElement(component, childProps, children);
}
return cloneElement(component, childProps);
}
return children ? Children.only(children) : null;
};
Element.propTypes = {
onRef: PropTypes.func,
children: PropTypes.node,
component: PropTypes.oneOfType([PropTypes.element, PropTypes.string, PropTypes.func])
};
export default Element;