or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

asset-resolution.mdbuiltin-components.mdcomponents.mdcomposition-helpers.mddependency-injection.mderror-handling.mdhydration.mdindex.mdinternal-render-helpers.mdlifecycle.mdreactivity.mdscheduler-timing.mdssr-context.mdvdom-rendering.mdwatch-effects.md

vdom-rendering.mddocs/

0

# Virtual DOM & Rendering

1

2

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

3

4

## Capabilities

5

6

### VNode Creation

7

8

Create virtual nodes representing DOM elements, components, and text.

9

10

```typescript { .api }

11

/**

12

* Creates a virtual node (shorthand function)

13

* @param type - Element tag, component, or special type

14

* @param props - Properties and attributes

15

* @param children - Child nodes or text content

16

* @returns Virtual node

17

*/

18

function h(type: string | Component, props?: VNodeProps | null, children?: VNodeArrayChildren): VNode;

19

function h(type: string | Component, children?: VNodeArrayChildren): VNode;

20

21

/**

22

* Creates a virtual node (full function)

23

* @param type - Node type (string, component, Symbol)

24

* @param props - Node properties and attributes

25

* @param children - Child nodes

26

* @param patchFlag - Optimization hint for diffing

27

* @param dynamicProps - Dynamic property names

28

* @returns Virtual node

29

*/

30

function createVNode(

31

type: VNodeTypes,

32

props?: VNodeProps | null,

33

children?: VNodeArrayChildren,

34

patchFlag?: number,

35

dynamicProps?: string[] | null

36

): VNode;

37

38

/**

39

* Clones a virtual node with optional additional props

40

* @param vnode - VNode to clone

41

* @param extraProps - Additional properties to merge

42

* @param mergeRef - Whether to merge refs

43

* @returns Cloned VNode

44

*/

45

function cloneVNode<T, U>(

46

vnode: VNode,

47

extraProps?: (T & VNodeProps) | null,

48

mergeRef?: boolean

49

): VNode;

50

51

/**

52

* Checks if a value is a VNode

53

* @param value - Value to check

54

* @returns True if value is a VNode

55

*/

56

function isVNode(value: unknown): value is VNode;

57

58

/**

59

* Merges multiple props objects into one

60

* @param args - Props objects to merge

61

* @returns Merged props object

62

*/

63

function mergeProps(...args: (VNodeProps | undefined)[]): VNodeProps;

64

```

65

66

**Usage Examples:**

67

68

```typescript

69

import { h, createVNode, cloneVNode, isVNode, defineComponent } from "@vue/runtime-core";

70

71

// Basic element creation with h()

72

const div = h('div', { class: 'container' }, 'Hello World');

73

74

// Element with multiple children

75

const header = h('header', [

76

h('h1', 'My App'),

77

h('nav', [

78

h('a', { href: '/home' }, 'Home'),

79

h('a', { href: '/about' }, 'About')

80

])

81

]);

82

83

// Component usage

84

const MyComponent = defineComponent({

85

props: { message: String },

86

render() {

87

return h('p', this.message);

88

}

89

});

90

91

const componentVNode = h(MyComponent, { message: 'Hello from component' });

92

93

// Using createVNode for more control

94

const customVNode = createVNode(

95

'button',

96

{

97

class: 'btn btn-primary',

98

onClick: () => console.log('clicked')

99

},

100

'Click me'

101

);

102

103

// Cloning VNodes

104

const originalBtn = h('button', { class: 'btn' }, 'Original');

105

const clonedBtn = cloneVNode(originalBtn, { class: 'btn btn-large' });

106

107

// Check if value is VNode

108

if (isVNode(div)) {

109

console.log('div is a VNode:', div.type); // 'div'

110

}

111

```

112

113

### VNode Types & Symbols

114

115

Special VNode types for different content types.

116

117

```typescript { .api }

118

/**

119

* Fragment symbol for multiple root elements

120

*/

121

const Fragment: unique symbol;

122

123

/**

124

* Text node symbol

125

*/

126

const Text: unique symbol;

127

128

/**

129

* Comment node symbol

130

*/

131

const Comment: unique symbol;

132

133

/**

134

* Static node symbol for hoisted content

135

*/

136

const Static: unique symbol;

137

```

138

139

**Usage Examples:**

140

141

```typescript

142

import { h, Fragment, Text, Comment, createVNode } from "@vue/runtime-core";

143

144

// Fragment for multiple root elements

145

const multipleRoots = h(Fragment, [

146

h('header', 'Header'),

147

h('main', 'Main content'),

148

h('footer', 'Footer')

149

]);

150

151

// Text node

152

const textNode = createVNode(Text, null, 'Plain text content');

153

154

// Comment node

155

const commentNode = createVNode(Comment, null, 'This is a comment');

156

157

// Using in render functions

158

const MyComponent = defineComponent({

159

render() {

160

return h(Fragment, [

161

h('h1', 'Title'),

162

h('p', 'Paragraph 1'),

163

h('p', 'Paragraph 2')

164

]);

165

}

166

});

167

```

168

169

### Custom Renderer Creation

170

171

Create custom renderers for different platforms or output targets.

172

173

```typescript { .api }

174

/**

175

* Creates a custom renderer with platform-specific operations

176

* @param options - Renderer configuration with platform operations

177

* @returns Renderer with render and createApp functions

178

*/

179

function createRenderer<

180

HostNode = RendererNode,

181

HostElement = RendererElement

182

>(options: RendererOptions<HostNode, HostElement>): Renderer<HostElement>;

183

184

/**

185

* Creates a custom hydration renderer for SSR

186

* @param options - Renderer configuration with hydration support

187

* @returns Hydration renderer

188

*/

189

function createHydrationRenderer<

190

HostNode = RendererNode,

191

HostElement = RendererElement

192

>(options: RendererOptions<HostNode, HostElement>): HydrationRenderer;

193

194

interface RendererOptions<HostNode = any, HostElement = any> {

195

// Node creation

196

createElement(type: string, namespace?: ElementNamespace): HostElement;

197

createText(text: string): HostNode;

198

createComment(text: string): HostNode;

199

200

// Node manipulation

201

insert(child: HostNode, parent: HostElement, anchor?: HostNode | null): void;

202

remove(child: HostNode): void;

203

204

// Content updates

205

setText(node: HostNode, text: string): void;

206

setElementText(node: HostElement, text: string): void;

207

208

// Property handling

209

patchProp(

210

el: HostElement,

211

key: string,

212

prevValue: any,

213

nextValue: any,

214

namespace?: ElementNamespace

215

): void;

216

217

// Tree traversal

218

parentNode(node: HostNode): HostElement | null;

219

nextSibling(node: HostNode): HostNode | null;

220

221

// Optional: namespace handling

222

querySelector?(selector: string): HostElement | null;

223

setScopeId?(el: HostElement, id: string): void;

224

cloneNode?(node: HostNode): HostNode;

225

insertStaticContent?(

226

content: string,

227

parent: HostElement,

228

anchor: HostNode | null,

229

namespace: ElementNamespace

230

): HostNode[];

231

}

232

```

233

234

**Usage Examples:**

235

236

```typescript

237

import { createRenderer, h } from "@vue/runtime-core";

238

239

// Canvas renderer example

240

interface CanvasNode {

241

type: string;

242

props: Record<string, any>;

243

children: CanvasNode[];

244

x?: number;

245

y?: number;

246

}

247

248

const canvasRenderer = createRenderer<CanvasNode, CanvasNode>({

249

createElement(type) {

250

return {

251

type,

252

props: {},

253

children: []

254

};

255

},

256

257

createText(text) {

258

return {

259

type: 'text',

260

props: { text },

261

children: []

262

};

263

},

264

265

createComment(text) {

266

return {

267

type: 'comment',

268

props: { text },

269

children: []

270

};

271

},

272

273

insert(child, parent, anchor) {

274

if (anchor) {

275

const index = parent.children.indexOf(anchor);

276

parent.children.splice(index, 0, child);

277

} else {

278

parent.children.push(child);

279

}

280

},

281

282

remove(child) {

283

// Implementation for removing from canvas

284

},

285

286

setText(node, text) {

287

if (node.type === 'text') {

288

node.props.text = text;

289

}

290

},

291

292

setElementText(node, text) {

293

node.children = [{

294

type: 'text',

295

props: { text },

296

children: []

297

}];

298

},

299

300

patchProp(el, key, prevValue, nextValue) {

301

el.props[key] = nextValue;

302

},

303

304

parentNode(node) {

305

// Return parent node

306

return null;

307

},

308

309

nextSibling(node) {

310

// Return next sibling

311

return null;

312

}

313

});

314

315

// Use the custom renderer

316

const { render, createApp } = canvasRenderer;

317

318

const canvasApp = createApp({

319

render() {

320

return h('rect', {

321

x: 10,

322

y: 10,

323

width: 100,

324

height: 50,

325

fill: 'blue'

326

});

327

}

328

});

329

```

330

331

### Low-level VNode Manipulation

332

333

Advanced VNode creation and manipulation functions.

334

335

```typescript { .api }

336

/**

337

* Creates a text VNode

338

* @param text - Text content

339

* @param flag - Patch flag for optimization

340

* @returns Text VNode

341

*/

342

function createTextVNode(text?: string, flag?: number): VNode;

343

344

/**

345

* Creates a comment VNode

346

* @param text - Comment text

347

* @param asBlock - Whether to create as block

348

* @returns Comment VNode

349

*/

350

function createCommentVNode(text?: string, asBlock?: boolean): VNode;

351

352

/**

353

* Creates a static VNode for hoisted content

354

* @param content - Static HTML content

355

* @param numberOfNodes - Number of nodes in content

356

* @returns Static VNode

357

*/

358

function createStaticVNode(content: string, numberOfNodes: number): VNode;

359

360

/**

361

* Creates an element VNode

362

* @param type - Element type

363

* @param props - Element properties

364

* @param children - Child nodes

365

* @param patchFlag - Optimization flag

366

* @param dynamicProps - Dynamic property names

367

* @returns Element VNode

368

*/

369

function createElementVNode(

370

type: string | typeof Fragment,

371

props?: VNodeProps | null,

372

children?: VNodeArrayChildren,

373

patchFlag?: number,

374

dynamicProps?: string[] | null

375

): VNode;

376

377

/**

378

* Creates an element block (tracked VNode)

379

* @param type - Element type

380

* @param props - Element properties

381

* @param children - Child nodes

382

* @param patchFlag - Optimization flag

383

* @param dynamicProps - Dynamic property names

384

* @returns Element block VNode

385

*/

386

function createElementBlock(

387

type: string,

388

props?: VNodeProps | null,

389

children?: VNodeArrayChildren,

390

patchFlag?: number,

391

dynamicProps?: string[] | null

392

): VNode;

393

```

394

395

## Types

396

397

```typescript { .api }

398

interface VNode<HostNode = RendererNode, HostElement = RendererElement> {

399

// Core properties

400

type: VNodeTypes;

401

props: VNodeProps | null;

402

key: string | number | symbol | null;

403

ref: VNodeRef | null;

404

children: VNodeNormalizedChildren;

405

406

// Internal properties

407

component: ComponentInternalInstance | null;

408

suspense: SuspenseBoundary | null;

409

ssrContext: Record<string, any> | null;

410

411

// Optimization

412

patchFlag: number;

413

dynamicProps: string[] | null;

414

dynamicChildren: VNode[] | null;

415

416

// Platform-specific

417

el: HostNode | null;

418

anchor: HostNode | null;

419

target: HostElement | null;

420

targetAnchor: HostNode | null;

421

}

422

423

type VNodeTypes = string | VNode | Component | typeof Text | typeof Static | typeof Comment | typeof Fragment;

424

425

interface VNodeProps {

426

key?: string | number | symbol;

427

ref?: VNodeRef;

428

ref_for?: boolean;

429

ref_key?: string;

430

431

// DOM properties

432

[key: string]: any;

433

}

434

435

type VNodeArrayChildren = Array<VNodeArrayChildren | VNodeChildAtom>;

436

437

type VNodeChildAtom = VNode | string | number | boolean | null | undefined | void;

438

439

type VNodeNormalizedChildren = string | VNodeArrayChildren | RawSlots | null;

440

441

interface VNodeRef {

442

(ref: Element | ComponentPublicInstance | null, refs: Record<string, any>): void;

443

}

444

445

type RendererNode = any;

446

type RendererElement = any;

447

448

interface Renderer<HostElement = RendererElement> {

449

render: RootRenderFunction<HostElement>;

450

createApp: CreateAppFunction<HostElement>;

451

}

452

453

interface HydrationRenderer extends Renderer<Element | ShadowRoot> {

454

hydrate: RootHydrateFunction;

455

}

456

457

type RootRenderFunction<HostElement = RendererElement> = (

458

vnode: VNode | null,

459

container: HostElement,

460

namespace?: ElementNamespace

461

) => void;

462

463

type ElementNamespace = 'svg' | 'mathml' | undefined;

464

```