| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- import {
- type Comment,
- type Fragment,
- type Text,
- type VNode,
- type VNodeArrayChildren,
- type VNodeProps,
- createVNode,
- isVNode,
- setBlockTracking,
- } from './vnode'
- import type { Teleport, TeleportProps } from './components/Teleport'
- import type { Suspense, SuspenseProps } from './components/Suspense'
- import { type IfAny, isArray, isObject } from '@vue/shared'
- import type { RawSlots } from './componentSlots'
- import type {
- Component,
- ComponentOptions,
- ConcreteComponent,
- FunctionalComponent,
- } from './component'
- import type { EmitsOptions } from './componentEmits'
- import type { DefineComponent } from './apiDefineComponent'
- // `h` is a more user-friendly version of `createVNode` that allows omitting the
- // props when possible. It is intended for manually written render functions.
- // Compiler-generated code uses `createVNode` because
- // 1. it is monomorphic and avoids the extra call overhead
- // 2. it allows specifying patchFlags for optimization
- /*
- // type only
- h('div')
- // type + props
- h('div', {})
- // type + omit props + children
- // Omit props does NOT support named slots
- h('div', []) // array
- h('div', 'foo') // text
- h('div', h('br')) // vnode
- h(Component, () => {}) // default slot
- // type + props + children
- h('div', {}, []) // array
- h('div', {}, 'foo') // text
- h('div', {}, h('br')) // vnode
- h(Component, {}, () => {}) // default slot
- h(Component, {}, {}) // named slots
- // named slots without props requires explicit `null` to avoid ambiguity
- h(Component, null, {})
- **/
- type RawProps = VNodeProps & {
- // used to differ from a single VNode object as children
- __v_isVNode?: never
- // used to differ from Array children
- [Symbol.iterator]?: never
- } & Record<string, any>
- type RawChildren =
- | string
- | number
- | boolean
- | VNode
- | VNodeArrayChildren
- | (() => any)
- // fake constructor type returned from `defineComponent`
- interface Constructor<P = any> {
- __isFragment?: never
- __isTeleport?: never
- __isSuspense?: never
- new (...args: any[]): { $props: P }
- }
- type HTMLElementEventHandler = {
- [K in keyof HTMLElementEventMap as `on${Capitalize<K>}`]?: (
- ev: HTMLElementEventMap[K],
- ) => any
- }
- // The following is a series of overloads for providing props validation of
- // manually written render functions.
- // element
- export function h<K extends keyof HTMLElementTagNameMap>(
- type: K,
- children?: RawChildren,
- ): VNode
- export function h<K extends keyof HTMLElementTagNameMap>(
- type: K,
- props?: (RawProps & HTMLElementEventHandler) | null,
- children?: RawChildren | RawSlots,
- ): VNode
- // custom element
- export function h(type: string, children?: RawChildren): VNode
- export function h(
- type: string,
- props?: RawProps | null,
- children?: RawChildren | RawSlots,
- ): VNode
- // text/comment
- export function h(
- type: typeof Text | typeof Comment,
- children?: string | number | boolean,
- ): VNode
- export function h(
- type: typeof Text | typeof Comment,
- props?: null,
- children?: string | number | boolean,
- ): VNode
- // fragment
- export function h(type: typeof Fragment, children?: VNodeArrayChildren): VNode
- export function h(
- type: typeof Fragment,
- props?: RawProps | null,
- children?: VNodeArrayChildren,
- ): VNode
- // teleport (target prop is required)
- export function h(
- type: typeof Teleport,
- props: RawProps & TeleportProps,
- children: RawChildren | RawSlots,
- ): VNode
- // suspense
- export function h(type: typeof Suspense, children?: RawChildren): VNode
- export function h(
- type: typeof Suspense,
- props?: (RawProps & SuspenseProps) | null,
- children?: RawChildren | RawSlots,
- ): VNode
- // functional component
- export function h<
- P,
- E extends EmitsOptions = {},
- S extends Record<string, any> = any,
- >(
- type: FunctionalComponent<P, any, S, any>,
- props?: (RawProps & P) | ({} extends P ? null : never),
- children?: RawChildren | IfAny<S, RawSlots, S>,
- ): VNode
- // catch-all for generic component types
- export function h(type: Component, children?: RawChildren): VNode
- // concrete component
- export function h<P>(
- type: ConcreteComponent | string,
- children?: RawChildren,
- ): VNode
- export function h<P>(
- type: ConcreteComponent<P> | string,
- props?: (RawProps & P) | ({} extends P ? null : never),
- children?: RawChildren,
- ): VNode
- // component without props
- export function h<P>(
- type: Component<P>,
- props?: (RawProps & P) | null,
- children?: RawChildren | RawSlots,
- ): VNode
- // exclude `defineComponent` constructors
- export function h<P>(
- type: ComponentOptions<P>,
- props?: (RawProps & P) | ({} extends P ? null : never),
- children?: RawChildren | RawSlots,
- ): VNode
- // fake constructor type returned by `defineComponent` or class component
- export function h(type: Constructor, children?: RawChildren): VNode
- export function h<P>(
- type: Constructor<P>,
- props?: (RawProps & P) | ({} extends P ? null : never),
- children?: RawChildren | RawSlots,
- ): VNode
- // fake constructor type returned by `defineComponent`
- export function h(type: DefineComponent, children?: RawChildren): VNode
- export function h<P>(
- type: DefineComponent<P>,
- props?: (RawProps & P) | ({} extends P ? null : never),
- children?: RawChildren | RawSlots,
- ): VNode
- // catch all types
- export function h(type: string | Component, children?: RawChildren): VNode
- export function h<P>(
- type: string | Component<P>,
- props?: (RawProps & P) | ({} extends P ? null : never),
- children?: RawChildren | RawSlots,
- ): VNode
- // Actual implementation
- export function h(type: any, propsOrChildren?: any, children?: any): VNode {
- try {
- // #6913 disable tracking block in h function
- setBlockTracking(-1)
- const l = arguments.length
- if (l === 2) {
- if (isObject(propsOrChildren) && !isArray(propsOrChildren)) {
- // single vnode without props
- if (isVNode(propsOrChildren)) {
- return createVNode(type, null, [propsOrChildren])
- }
- // props without children
- return createVNode(type, propsOrChildren)
- } else {
- // omit props
- return createVNode(type, null, propsOrChildren)
- }
- } else {
- if (l > 3) {
- children = Array.prototype.slice.call(arguments, 2)
- } else if (l === 3 && isVNode(children)) {
- children = [children]
- }
- return createVNode(type, propsOrChildren, children)
- }
- } finally {
- setBlockTracking(1)
- }
- }
|