preact
Version:
Fast 3kb React-compatible Virtual DOM library.
103 lines (92 loc) • 3.03 kB
JavaScript
import options from './options';
/**
* Create an virtual node (used for JSX)
* @param {import('./internal').VNode["type"]} type The node name or Component
* constructor for this virtual node
* @param {object | null | undefined} [props] The properties of the virtual node
* @param {Array<import('.').ComponentChildren>} [children] The children of the virtual node
* @returns {import('./internal').VNode}
*/
export function createElement(type, props, children) {
let normalizedProps = {},
i;
for (i in props) {
if (i !== 'key' && i !== 'ref') normalizedProps[i] = props[i];
}
if (arguments.length > 3) {
children = [children];
// https://github.com/preactjs/preact/issues/1916
for (i = 3; i < arguments.length; i++) {
children.push(arguments[i]);
}
}
if (children != null) {
normalizedProps.children = children;
}
// If a Component VNode, check for and apply defaultProps
// Note: type may be undefined in development, must never error here.
if (typeof type == 'function' && type.defaultProps != null) {
for (i in type.defaultProps) {
if (normalizedProps[i] === undefined) {
normalizedProps[i] = type.defaultProps[i];
}
}
}
return createVNode(
type,
normalizedProps,
props && props.key,
props && props.ref,
null
);
}
/**
* Create a VNode (used internally by Preact)
* @param {import('./internal').VNode["type"]} type The node name or Component
* Constructor for this virtual node
* @param {object | string | number | null} props The properties of this virtual node.
* If this virtual node represents a text node, this is the text of the node (string or number).
* @param {string | number | null} key The key for this virtual node, used when
* diffing it against its children
* @param {import('./internal').VNode["ref"]} ref The ref property that will
* receive a reference to its created child
* @returns {import('./internal').VNode}
*/
export function createVNode(type, props, key, ref, original) {
// V8 seems to be better at detecting type shapes if the object is allocated from the same call site
// Do not inline into createElement and coerceToVNode!
const vnode = {
type,
props,
key,
ref,
_children: null,
_parent: null,
_depth: 0,
_dom: null,
// _nextDom must be initialized to undefined b/c it will eventually
// be set to dom.nextSibling which can return `null` and it is important
// to be able to distinguish between an uninitialized _nextDom and
// a _nextDom that has been set to `null`
_nextDom: undefined,
_component: null,
constructor: undefined,
_original: original
};
if (original == null) vnode._original = vnode;
if (options.vnode) options.vnode(vnode);
return vnode;
}
export function createRef() {
return {};
}
export function Fragment(props) {
return props.children;
}
/**
* Check if a the argument is a valid Preact VNode.
* @param {*} vnode
* @returns {vnode is import('./internal').VNode}
*/
export const isValidElement = vnode =>
vnode != null && vnode.constructor === undefined;