UNPKG

react-element

Version:
70 lines (62 loc) 2.04 kB
/* eslint prefer-rest-params: 0 */ import cx from 'classnames' import PropTypes from 'prop-types' import {Children, cloneElement, createElement, isValidElement} from 'react' const reEvent = /^on\w+$/ const isFunction = f => typeof f === 'function' // 属性后定义后覆盖(除了 class 始终拼接起来),处理函数先定义先执行 const mergeProps = (destProps, srcProps) => { const className = cx(srcProps.className, destProps.className) const resultProps = {...destProps, ...srcProps, ...(className && {className})} // keep event handlers Object.keys(destProps).forEach(key => { const destHandler = destProps[key] const 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> */ const Element = ({component, children, ...ownProps}) => { const 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)) { const 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