UNPKG

nervjs

Version:

A react-like framework based on virtual-dom

122 lines (115 loc) 4.2 kB
import h from '#/h' import SVGPropertyConfig from '#/svg-property-config' import { isFunction, isString, isNumber, isBoolean, isObject } from '~' import FullComponent from './full-component' import StatelessComponent from './stateless-component' import CurrentOwner from './current-owner' import RefHook from './hooks/ref-hook' import HtmlHook from './hooks/html-hook' import EventHook from './hooks/event-hook' import AttributeHook from './hooks/attribute-hook' const IS_NON_DIMENSIONAL = /acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i const EMPTY_CHILDREN = [] function transformPropsForRealTag (tagName, props) { let newProps = {} const DOMAttributeNamespaces = SVGPropertyConfig.DOMAttributeNamespaces for (let propName in props) { const propValue = props[propName] const originalPropName = propName const domAttributeName = SVGPropertyConfig.DOMAttributeNames[propName] propName = domAttributeName || propName if (DOMAttributeNamespaces.hasOwnProperty(originalPropName) && (isString(propValue) || isNumber(propValue) || isBoolean(propValue))) { const namespace = DOMAttributeNamespaces[originalPropName] newProps[propName] = !(propValue instanceof AttributeHook) ? new AttributeHook(namespace, propValue) : propValue continue } if ((propName === 'id' || propName === 'className' || propName === 'namespace') && propValue !== undefined) { newProps[propName] = propValue continue } if (propName === 'ref') { newProps[propName] = !(propValue instanceof RefHook) ? new RefHook(propValue) : propValue continue } if (propName === 'dangerouslySetInnerHTML') { newProps[propName] = !(propValue instanceof HtmlHook) ? new HtmlHook(propValue) : propValue continue } // 收集事件 if (propName.charAt(0) === 'o' && propName.charAt(1) === 'n') { newProps[propName] = !(propValue instanceof EventHook) ? new EventHook(propName, propValue) : propValue continue } if (propName === 'defaultValue') { newProps.value = props.value || props.defaultValue continue } if (propName === 'style') { if (isString(propValue)) { newProps[propName] = propValue } else if (isObject(propValue)) { for (let styleName in propValue) { let styleValue = propValue[styleName] if (styleValue !== undefined && (isString(styleValue) || !isNaN(styleValue))) { styleValue = isNumber(styleValue) && IS_NON_DIMENSIONAL.test(styleName) === false ? (styleValue + 'px') : styleValue newProps[propName] = newProps[propName] || {} newProps[propName][styleName] = styleValue } } } continue } newProps[propName] = propValue } return newProps } function transformPropsForComponent (props) { let newProps = {} for (let propName in props) { let propValue = props[propName] newProps[propName] = propValue } return newProps } function createElement (tagName, properties) { let children = EMPTY_CHILDREN for (let i = 2, len = arguments.length; i < len; i++) { const argumentsItem = arguments[i] if (Array.isArray(argumentsItem)) { argumentsItem.forEach(item => { if (children === EMPTY_CHILDREN) { children = [item] } else { children.push(item) } }) } else if (children === EMPTY_CHILDREN) { children = [argumentsItem] } else { children.push(argumentsItem) } } let props if (isString(tagName)) { props = transformPropsForRealTag(tagName, properties) props.owner = CurrentOwner.current return h(tagName, props, children) } else if (isFunction(tagName)) { props = transformPropsForComponent(properties) if (props.children) { if (!Array.isArray(props.children)) { props.children = [props.children] } } else { props.children = children } props.owner = CurrentOwner.current return (tagName.prototype && tagName.prototype.render) ? new FullComponent(tagName, props) : new StatelessComponent(tagName, props) } return tagName } export default createElement