CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-vue--runtime-core

Vue.js 3 runtime core library providing foundational APIs for building custom renderers and managing reactive component systems

Pending
Overview
Eval results
Files

vdom-rendering.mddocs/

Virtual DOM & Rendering

Vue's Virtual DOM system provides efficient DOM manipulation through virtual node abstractions and custom renderer support for targeting different platforms.

Capabilities

VNode Creation

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'
}

VNode Types & Symbols

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')
    ]);
  }
});

Custom Renderer Creation

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' 
    });
  }
});

Low-level VNode Manipulation

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;

Types

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

docs

asset-resolution.md

builtin-components.md

components.md

composition-helpers.md

dependency-injection.md

error-handling.md

hydration.md

index.md

internal-render-helpers.md

lifecycle.md

reactivity.md

scheduler-timing.md

ssr-context.md

vdom-rendering.md

watch-effects.md

tile.json