Vue.js 3 runtime core library providing foundational APIs for building custom renderers and managing reactive component systems
—
Vue's Virtual DOM system provides efficient DOM manipulation through virtual node abstractions and custom renderer support for targeting different platforms.
Create virtual nodes representing DOM elements, components, and text.
/**
* Creates a virtual node (shorthand function)
* @param type - Element tag, component, or special type
* @param props - Properties and attributes
* @param children - Child nodes or text content
* @returns Virtual node
*/
function h(type: string | Component, props?: VNodeProps | null, children?: VNodeArrayChildren): VNode;
function h(type: string | Component, children?: VNodeArrayChildren): VNode;
/**
* Creates a virtual node (full function)
* @param type - Node type (string, component, Symbol)
* @param props - Node properties and attributes
* @param children - Child nodes
* @param patchFlag - Optimization hint for diffing
* @param dynamicProps - Dynamic property names
* @returns Virtual node
*/
function createVNode(
type: VNodeTypes,
props?: VNodeProps | null,
children?: VNodeArrayChildren,
patchFlag?: number,
dynamicProps?: string[] | null
): VNode;
/**
* Clones a virtual node with optional additional props
* @param vnode - VNode to clone
* @param extraProps - Additional properties to merge
* @param mergeRef - Whether to merge refs
* @returns Cloned VNode
*/
function cloneVNode<T, U>(
vnode: VNode,
extraProps?: (T & VNodeProps) | null,
mergeRef?: boolean
): VNode;
/**
* Checks if a value is a VNode
* @param value - Value to check
* @returns True if value is a VNode
*/
function isVNode(value: unknown): value is VNode;
/**
* Merges multiple props objects into one
* @param args - Props objects to merge
* @returns Merged props object
*/
function mergeProps(...args: (VNodeProps | undefined)[]): VNodeProps;Usage Examples:
import { h, createVNode, cloneVNode, isVNode, defineComponent } from "@vue/runtime-core";
// Basic element creation with h()
const div = h('div', { class: 'container' }, 'Hello World');
// Element with multiple children
const header = h('header', [
h('h1', 'My App'),
h('nav', [
h('a', { href: '/home' }, 'Home'),
h('a', { href: '/about' }, 'About')
])
]);
// Component usage
const MyComponent = defineComponent({
props: { message: String },
render() {
return h('p', this.message);
}
});
const componentVNode = h(MyComponent, { message: 'Hello from component' });
// Using createVNode for more control
const customVNode = createVNode(
'button',
{
class: 'btn btn-primary',
onClick: () => console.log('clicked')
},
'Click me'
);
// Cloning VNodes
const originalBtn = h('button', { class: 'btn' }, 'Original');
const clonedBtn = cloneVNode(originalBtn, { class: 'btn btn-large' });
// Check if value is VNode
if (isVNode(div)) {
console.log('div is a VNode:', div.type); // 'div'
}Special VNode types for different content types.
/**
* Fragment symbol for multiple root elements
*/
const Fragment: unique symbol;
/**
* Text node symbol
*/
const Text: unique symbol;
/**
* Comment node symbol
*/
const Comment: unique symbol;
/**
* Static node symbol for hoisted content
*/
const Static: unique symbol;Usage Examples:
import { h, Fragment, Text, Comment, createVNode } from "@vue/runtime-core";
// Fragment for multiple root elements
const multipleRoots = h(Fragment, [
h('header', 'Header'),
h('main', 'Main content'),
h('footer', 'Footer')
]);
// Text node
const textNode = createVNode(Text, null, 'Plain text content');
// Comment node
const commentNode = createVNode(Comment, null, 'This is a comment');
// Using in render functions
const MyComponent = defineComponent({
render() {
return h(Fragment, [
h('h1', 'Title'),
h('p', 'Paragraph 1'),
h('p', 'Paragraph 2')
]);
}
});Create custom renderers for different platforms or output targets.
/**
* Creates a custom renderer with platform-specific operations
* @param options - Renderer configuration with platform operations
* @returns Renderer with render and createApp functions
*/
function createRenderer<
HostNode = RendererNode,
HostElement = RendererElement
>(options: RendererOptions<HostNode, HostElement>): Renderer<HostElement>;
/**
* Creates a custom hydration renderer for SSR
* @param options - Renderer configuration with hydration support
* @returns Hydration renderer
*/
function createHydrationRenderer<
HostNode = RendererNode,
HostElement = RendererElement
>(options: RendererOptions<HostNode, HostElement>): HydrationRenderer;
interface RendererOptions<HostNode = any, HostElement = any> {
// Node creation
createElement(type: string, namespace?: ElementNamespace): HostElement;
createText(text: string): HostNode;
createComment(text: string): HostNode;
// Node manipulation
insert(child: HostNode, parent: HostElement, anchor?: HostNode | null): void;
remove(child: HostNode): void;
// Content updates
setText(node: HostNode, text: string): void;
setElementText(node: HostElement, text: string): void;
// Property handling
patchProp(
el: HostElement,
key: string,
prevValue: any,
nextValue: any,
namespace?: ElementNamespace
): void;
// Tree traversal
parentNode(node: HostNode): HostElement | null;
nextSibling(node: HostNode): HostNode | null;
// Optional: namespace handling
querySelector?(selector: string): HostElement | null;
setScopeId?(el: HostElement, id: string): void;
cloneNode?(node: HostNode): HostNode;
insertStaticContent?(
content: string,
parent: HostElement,
anchor: HostNode | null,
namespace: ElementNamespace
): HostNode[];
}Usage Examples:
import { createRenderer, h } from "@vue/runtime-core";
// Canvas renderer example
interface CanvasNode {
type: string;
props: Record<string, any>;
children: CanvasNode[];
x?: number;
y?: number;
}
const canvasRenderer = createRenderer<CanvasNode, CanvasNode>({
createElement(type) {
return {
type,
props: {},
children: []
};
},
createText(text) {
return {
type: 'text',
props: { text },
children: []
};
},
createComment(text) {
return {
type: 'comment',
props: { text },
children: []
};
},
insert(child, parent, anchor) {
if (anchor) {
const index = parent.children.indexOf(anchor);
parent.children.splice(index, 0, child);
} else {
parent.children.push(child);
}
},
remove(child) {
// Implementation for removing from canvas
},
setText(node, text) {
if (node.type === 'text') {
node.props.text = text;
}
},
setElementText(node, text) {
node.children = [{
type: 'text',
props: { text },
children: []
}];
},
patchProp(el, key, prevValue, nextValue) {
el.props[key] = nextValue;
},
parentNode(node) {
// Return parent node
return null;
},
nextSibling(node) {
// Return next sibling
return null;
}
});
// Use the custom renderer
const { render, createApp } = canvasRenderer;
const canvasApp = createApp({
render() {
return h('rect', {
x: 10,
y: 10,
width: 100,
height: 50,
fill: 'blue'
});
}
});Advanced VNode creation and manipulation functions.
/**
* Creates a text VNode
* @param text - Text content
* @param flag - Patch flag for optimization
* @returns Text VNode
*/
function createTextVNode(text?: string, flag?: number): VNode;
/**
* Creates a comment VNode
* @param text - Comment text
* @param asBlock - Whether to create as block
* @returns Comment VNode
*/
function createCommentVNode(text?: string, asBlock?: boolean): VNode;
/**
* Creates a static VNode for hoisted content
* @param content - Static HTML content
* @param numberOfNodes - Number of nodes in content
* @returns Static VNode
*/
function createStaticVNode(content: string, numberOfNodes: number): VNode;
/**
* Creates an element VNode
* @param type - Element type
* @param props - Element properties
* @param children - Child nodes
* @param patchFlag - Optimization flag
* @param dynamicProps - Dynamic property names
* @returns Element VNode
*/
function createElementVNode(
type: string | typeof Fragment,
props?: VNodeProps | null,
children?: VNodeArrayChildren,
patchFlag?: number,
dynamicProps?: string[] | null
): VNode;
/**
* Creates an element block (tracked VNode)
* @param type - Element type
* @param props - Element properties
* @param children - Child nodes
* @param patchFlag - Optimization flag
* @param dynamicProps - Dynamic property names
* @returns Element block VNode
*/
function createElementBlock(
type: string,
props?: VNodeProps | null,
children?: VNodeArrayChildren,
patchFlag?: number,
dynamicProps?: string[] | null
): VNode;interface VNode<HostNode = RendererNode, HostElement = RendererElement> {
// Core properties
type: VNodeTypes;
props: VNodeProps | null;
key: string | number | symbol | null;
ref: VNodeRef | null;
children: VNodeNormalizedChildren;
// Internal properties
component: ComponentInternalInstance | null;
suspense: SuspenseBoundary | null;
ssrContext: Record<string, any> | null;
// Optimization
patchFlag: number;
dynamicProps: string[] | null;
dynamicChildren: VNode[] | null;
// Platform-specific
el: HostNode | null;
anchor: HostNode | null;
target: HostElement | null;
targetAnchor: HostNode | null;
}
type VNodeTypes = string | VNode | Component | typeof Text | typeof Static | typeof Comment | typeof Fragment;
interface VNodeProps {
key?: string | number | symbol;
ref?: VNodeRef;
ref_for?: boolean;
ref_key?: string;
// DOM properties
[key: string]: any;
}
type VNodeArrayChildren = Array<VNodeArrayChildren | VNodeChildAtom>;
type VNodeChildAtom = VNode | string | number | boolean | null | undefined | void;
type VNodeNormalizedChildren = string | VNodeArrayChildren | RawSlots | null;
interface VNodeRef {
(ref: Element | ComponentPublicInstance | null, refs: Record<string, any>): void;
}
type RendererNode = any;
type RendererElement = any;
interface Renderer<HostElement = RendererElement> {
render: RootRenderFunction<HostElement>;
createApp: CreateAppFunction<HostElement>;
}
interface HydrationRenderer extends Renderer<Element | ShadowRoot> {
hydrate: RootHydrateFunction;
}
type RootRenderFunction<HostElement = RendererElement> = (
vnode: VNode | null,
container: HostElement,
namespace?: ElementNamespace
) => void;
type ElementNamespace = 'svg' | 'mathml' | undefined;Install with Tessl CLI
npx tessl i tessl/npm-vue--runtime-core