Skip to main content
API for creating Virtual DOM nodes using render functions. The h() function and related APIs allow you to manually write render functions instead of using templates.

h()

Creates a Virtual Node (VNode). A more user-friendly version of createVNode() that allows omitting props when possible. Type Signature:
// Element
function h(
  type: string,
  props?: RawProps | null,
  children?: RawChildren | RawSlots
): VNode

// Component
function h(
  type: Component,
  props?: (RawProps & ComponentProps) | null,
  children?: RawChildren | RawSlots
): VNode

// Fragment, Teleport, Suspense
function h(
  type: typeof Fragment | typeof Teleport | typeof Suspense,
  props?: RawProps | null,
  children?: RawChildren
): VNode
type
string | Component | symbol
required
The type of VNode to create. Can be:
  • HTML tag name as string (e.g., 'div', 'span')
  • Component object or constructor
  • Special symbols: Fragment, Text, Comment, Teleport, Suspense
props
object | null
Props and attributes to apply to the element or component. Can include:
  • Standard HTML attributes
  • Component props
  • Event listeners (e.g., onClick, onInput)
  • Special properties (key, ref, etc.)
Set to null or omit when passing children without props.
children
RawChildren | RawSlots
The children of the VNode. Can be:
  • String or number (text content)
  • Single VNode
  • Array of VNodes
  • Function (default slot for components)
  • Object of slot functions (named slots for components)

Returns

A VNode object representing the virtual DOM node.

Basic Usage

import { h } from 'vue'

export default {
  render() {
    // Element with no props or children
    return h('div')
  }
}

Element with Props

import { h } from 'vue'

export default {
  render() {
    return h(
      'div',
      {
        id: 'foo',
        class: 'bar',
        onClick: () => console.log('clicked')
      },
      'Hello'
    )
  }
}

Nested Elements

import { h } from 'vue'

export default {
  render() {
    return h('div', { class: 'container' }, [
      h('h1', 'Title'),
      h('p', 'Paragraph text'),
      h('button', { onClick: this.handleClick }, 'Click me')
    ])
  }
}

Omitting Props

import { h } from 'vue'

// When passing children without props, omit the second argument
h('div', [
  h('span', 'Hello')
])

// Text child
h('div', 'Hello')

// Single VNode child
h('div', h('span', 'Hello'))

Component Usage

import { h } from 'vue'
import MyComponent from './MyComponent.vue'

export default {
  render() {
    // Component with props
    return h(MyComponent, {
      msg: 'Hello',
      onCustomEvent: this.handleEvent
    })
  }
}

Named Slots

import { h } from 'vue'
import MyComponent from './MyComponent.vue'

export default {
  render() {
    return h(MyComponent, null, {
      // Object of slot functions
      default: () => 'Default slot content',
      header: () => h('h1', 'Header'),
      footer: () => h('p', 'Footer')
    })
  }
}

Fragments

import { h, Fragment } from 'vue'

export default {
  render() {
    return h(Fragment, [
      h('div', 'First'),
      h('div', 'Second'),
      h('div', 'Third')
    ])
  }
}
The compiler converts templates to createVNode() calls, not h(). Use h() only in manually written render functions.

createVNode()

Creates a Virtual Node. This is the internal function used by the compiler. Use h() for manually written render functions. Type Signature:
function createVNode(
  type: VNodeTypes,
  props?: VNodeProps | null,
  children?: unknown,
  patchFlag?: number,
  dynamicProps?: string[] | null,
  isBlockNode?: boolean
): VNode
type
VNodeTypes
required
The type of VNode (string, Component, or symbol).
props
VNodeProps | null
Props object including key, ref, and other attributes.
children
unknown
Children nodes (string, VNode, or array of VNodes).
patchFlag
number
Optimization hint for the patch process (compiler-generated).
dynamicProps
string[] | null
Array of dynamic prop keys for optimization (compiler-generated).
isBlockNode
boolean
Whether this VNode should be treated as a block node.

Returns

A VNode object.

Usage

import { createVNode } from 'vue'

const vnode = createVNode('div', { id: 'foo' }, 'hello')
Prefer h() for manual render functions. createVNode() is primarily for compiler-generated code and advanced use cases.

VNode Interface

The VNode interface represents a Virtual DOM node. Type Definition:
interface VNode<
  HostNode = RendererNode,
  HostElement = RendererElement,
  ExtraProps = { [key: string]: any }
> {
  type: VNodeTypes
  props: (VNodeProps & ExtraProps) | null
  key: PropertyKey | null
  ref: VNodeNormalizedRef | null
  children: VNodeNormalizedChildren
  component: ComponentInternalInstance | null
  
  // DOM
  el: HostNode | null
  anchor: HostNode | null
  target: HostElement | null
  
  // Optimization
  shapeFlag: number
  patchFlag: number
  dynamicProps: string[] | null
  dynamicChildren: VNode[] | null
}

Key Properties

type
VNodeTypes
The type of the VNode (tag name, component, or symbol).
props
VNodeProps | null
Props and attributes including key, ref, and event listeners.
children
VNodeNormalizedChildren
Child VNodes, text content, or slot functions.
key
PropertyKey | null
Unique key for list rendering optimization.
ref
VNodeNormalizedRef | null
Template ref for accessing the DOM element or component instance.
el
HostNode | null
Reference to the actual DOM node (set during mounting).
component
ComponentInternalInstance | null
Reference to the component instance (for component VNodes).

VNode Types

Special symbols and types used in VNode creation.

Fragment

Symbol for creating fragment nodes (multiple root elements).
import { h, Fragment } from 'vue'

h(Fragment, [
  h('div', 'First'),
  h('div', 'Second')
])

Text

Symbol for creating text nodes.
import { h, Text } from 'vue'

h(Text, 'Hello world')

Comment

Symbol for creating comment nodes.
import { h, Comment } from 'vue'

h(Comment, 'This is a comment')

isVNode()

Checks if a value is a VNode. Type Signature:
function isVNode(value: unknown): value is VNode
value
unknown
required
The value to check.

Returns

true if the value is a VNode, false otherwise.

Example

import { h, isVNode } from 'vue'

const vnode = h('div')
const plain = { type: 'div' }

console.log(isVNode(vnode)) // true
console.log(isVNode(plain)) // false

cloneVNode()

Clones a VNode with optional props and children override. Type Signature:
function cloneVNode(
  vnode: VNode,
  extraProps?: VNodeProps | null,
  mergeRef?: boolean
): VNode
vnode
VNode
required
The VNode to clone.
extraProps
VNodeProps | null
Additional props to merge with the original props.
mergeRef
boolean
Whether to merge the ref. Defaults to false.

Returns

A new cloned VNode.

Example

import { h, cloneVNode } from 'vue'

const original = h('div', { class: 'foo' }, 'Hello')
const cloned = cloneVNode(original, { id: 'bar' })

// cloned has both class="foo" and id="bar"
Cloning VNodes is useful for slot manipulation and higher-order component patterns.

Build docs developers (and LLMs) love