or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

bom.mddom.mdframework-integration.mdindex.mdtypes.mdutilities.md

dom.mddocs/

0

# Document Object Model (DOM) APIs

1

2

Complete virtual DOM implementation optimized for mini-program platforms while maintaining web compatibility. The DOM module provides familiar web APIs including nodes, elements, events, and style management.

3

4

## Overview

5

6

The DOM implementation creates a standardized document structure that compiles efficiently to mini-program data structures. Key features include:

7

8

- **Virtual Nodes**: Complete DOM node hierarchy (Element, Text, Comment)

9

- **Style Management**: CSS properties, class lists, and computed styles

10

- **Event System**: Web-compatible events with mini-program integration

11

- **Mutation Observation**: Change tracking and lifecycle integration

12

- **Path-based Updates**: Efficient rendering with incremental updates

13

- **Component Aliasing**: Platform-specific component mapping

14

15

## Node Hierarchy

16

17

The DOM follows standard web patterns with optimizations for mini-programs:

18

19

```

20

TaroEventTarget (base)

21

↳ TaroNode (abstract base)

22

↳ TaroElement (general elements)

23

↳ FormElement (form inputs)

24

↳ SVGElement (SVG elements)

25

↳ TaroRootElement (container root)

26

↳ TaroText (text nodes)

27

```

28

29

## Core Node Classes

30

31

### TaroNode

32

33

```typescript { .api }

34

import { TaroNode } from '@tarojs/runtime'

35

36

abstract class TaroNode extends TaroEventTarget {

37

// Identity

38

readonly uid: string // Unique identifier

39

readonly sid: string // Scoped identifier

40

readonly nodeType: number // Node type constant

41

readonly nodeName: string // Tag name (uppercase)

42

43

// Tree structure

44

parentNode: TaroNode | null

45

childNodes: TaroNode[]

46

47

// Computed properties

48

get nextSibling(): TaroNode | null

49

get previousSibling(): TaroNode | null

50

get parentElement(): TaroElement | null

51

get firstChild(): TaroNode | null

52

get lastChild(): TaroNode | null

53

54

// Path properties (for updates)

55

get _path(): string // Dot-notation path from root

56

get _root(): TaroRootElement | null // Root container

57

58

// Tree manipulation

59

appendChild(child: TaroNode): TaroNode

60

insertBefore(newChild: TaroNode, referenceChild: TaroNode | null): TaroNode

61

replaceChild(newChild: TaroNode, oldChild: TaroNode): TaroNode

62

removeChild(child: TaroNode): TaroNode

63

remove(): void

64

65

// Utilities

66

hasChildNodes(): boolean

67

enqueueUpdate(): void // Trigger update batching

68

}

69

70

// Node type constants

71

const ELEMENT_NODE = 1

72

const TEXT_NODE = 3

73

const COMMENT_NODE = 8

74

const DOCUMENT_NODE = 9

75

```

76

77

#### Key Features

78

79

- **Unique Identifiers**: Each node gets a unique `uid` and scoped `sid`

80

- **Path Tracking**: Automatic path calculation for efficient updates

81

- **Update Batching**: Changes trigger batched updates via `enqueueUpdate()`

82

- **Comment Filtering**: Comment nodes are filtered from `childNodes` by default

83

84

#### Usage Examples

85

86

```typescript

87

// Create node tree

88

const parent = document.createElement('view')

89

const child1 = document.createElement('text')

90

const child2 = document.createTextNode('Hello')

91

92

// Build tree structure

93

parent.appendChild(child1)

94

parent.appendChild(child2)

95

96

// Navigate tree

97

console.log('Parent:', child1.parentNode) // parent element

98

console.log('Next sibling:', child1.nextSibling) // child2

99

console.log('First child:', parent.firstChild) // child1

100

console.log('Has children:', parent.hasChildNodes()) // true

101

102

// Get update path

103

console.log('Node path:', child1._path) // "root.cn.[0].cn.[0]"

104

console.log('Root element:', child1._root) // TaroRootElement

105

106

// Tree manipulation

107

const newChild = document.createElement('image')

108

parent.insertBefore(newChild, child2) // Insert between child1 and child2

109

parent.removeChild(child1) // Remove child1

110

child2.remove() // Remove child2 directly

111

```

112

113

### TaroElement

114

115

```typescript { .api }

116

import { TaroElement } from '@tarojs/runtime'

117

118

class TaroElement extends TaroNode {

119

// Element properties

120

tagName: string // Tag name (lowercase)

121

props: Record<string, any> // Element properties/attributes

122

123

// Style and classes

124

style: Style // CSS style object

125

classList: ClassList // CSS class management

126

dataset: Record<string, string> // Data attributes

127

128

// Content properties

129

id: string // Element ID

130

className: string // CSS classes

131

innerHTML: string // Inner HTML content

132

textContent: string // Text content

133

cssText: string // Inline styles

134

135

// Collections

136

children: TaroElement[] // Child elements (no text nodes)

137

attributes: Record<string, string> // All attributes

138

139

// Attribute methods

140

hasAttribute(name: string): boolean

141

hasAttributes(): boolean

142

getAttribute(name: string): string | null

143

setAttribute(name: string, value: string | number | boolean): void

144

removeAttribute(name: string): void

145

146

// Element selection

147

getElementsByTagName(tagName: string): TaroElement[]

148

getElementsByClassName(className: string): TaroElement[]

149

150

// Focus and interaction

151

focus(): void

152

blur(): void

153

154

// Event handling (inherited from TaroEventTarget)

155

addEventListener(type: string, handler: EventListener, options?: AddEventListenerOptions): void

156

removeEventListener(type: string, handler: EventListener): void

157

dispatchEvent(event: TaroEvent): boolean

158

}

159

```

160

161

#### Key Features

162

163

- **Component Aliasing**: Automatic mapping to platform-specific components

164

- **View Optimization**: Special handling for `pure-view`, `static-view`, `catch-view`

165

- **Style Management**: Integrated CSS property and class handling

166

- **Attribute Sync**: Automatic synchronization between props and attributes

167

- **Content Management**: Support for both `innerHTML` and `textContent`

168

169

#### Usage Examples

170

171

```typescript

172

// Create and configure element

173

const view = document.createElement('view')

174

view.id = 'main-container'

175

view.className = 'container active'

176

view.setAttribute('data-test', 'value')

177

178

// Style management

179

view.style.setProperty('background-color', '#ffffff')

180

view.style.setProperty('padding', '16px')

181

view.cssText = 'color: red; font-size: 14px;'

182

183

// Class management

184

view.classList.add('highlighted')

185

view.classList.remove('active')

186

view.classList.toggle('visible')

187

188

// Content manipulation

189

view.textContent = 'Hello World'

190

view.innerHTML = '<text>Formatted <text class="bold">content</text></text>'

191

192

// Attribute access

193

console.log('ID:', view.getAttribute('id')) // "main-container"

194

console.log('Has data attr:', view.hasAttribute('data-test')) // true

195

console.log('All attributes:', view.attributes) // { id: "main-container", ... }

196

197

// Element selection

198

const textElements = view.getElementsByTagName('text')

199

const boldElements = view.getElementsByClassName('bold')

200

201

// Dataset access (data-* attributes)

202

view.setAttribute('data-user-id', '123')

203

console.log('User ID:', view.dataset.userId) // "123"

204

205

// Event handling

206

view.addEventListener('tap', (event) => {

207

console.log('Element tapped:', event.target)

208

})

209

210

// Focus management

211

view.focus() // Set focus to element

212

view.blur() // Remove focus

213

```

214

215

### TaroText

216

217

```typescript { .api }

218

import { TaroText } from '@tarojs/runtime'

219

220

class TaroText extends TaroNode {

221

// Text content

222

private _value: string // Internal text value

223

224

// Text properties (all reference _value)

225

get textContent(): string

226

set textContent(value: string)

227

228

get nodeValue(): string

229

set nodeValue(value: string)

230

231

get data(): string

232

set data(value: string)

233

234

// Node type

235

nodeType: 3 // TEXT_NODE constant

236

nodeName: '#text' // Standard text node name

237

}

238

```

239

240

#### Key Features

241

242

- **Automatic Updates**: Text changes automatically trigger path-based updates

243

- **Multiple Accessors**: Standard web APIs (`textContent`, `nodeValue`, `data`)

244

- **Mutation Recording**: Text modifications are tracked for mini-program updates

245

246

#### Usage Examples

247

248

```typescript

249

// Create text node

250

const textNode = document.createTextNode('Initial text')

251

252

// Modify content (all equivalent)

253

textNode.textContent = 'Updated text'

254

textNode.nodeValue = 'Updated text'

255

textNode.data = 'Updated text'

256

257

// Access content

258

console.log('Text:', textNode.textContent) // "Updated text"

259

console.log('Value:', textNode.nodeValue) // "Updated text"

260

console.log('Data:', textNode.data) // "Updated text"

261

262

// Add to element

263

const element = document.createElement('text')

264

element.appendChild(textNode)

265

266

// Text content propagates to parent

267

console.log('Element text:', element.textContent) // "Updated text"

268

```

269

270

### TaroRootElement

271

272

```typescript { .api }

273

import { TaroRootElement } from '@tarojs/runtime'

274

275

class TaroRootElement extends TaroElement {

276

// Update management

277

pendingUpdate: boolean // Whether update is queued

278

updatePayloads: UpdatePayload[] // Queued updates

279

280

// Mini-program context

281

ctx: MpInstance | null // Page/component instance

282

283

// Update lifecycle

284

enqueueUpdate(): void // Queue update for next tick

285

performUpdate(): void // Execute pending updates

286

scheduleTask(task: () => void): void // Schedule async task

287

288

// Update callbacks

289

enqueueUpdateCallback(callback: () => void): void // Add update callback

290

flushUpdateCallback(): void // Execute all callbacks

291

292

// Custom wrapper handling

293

customWrapperCache: Map<string, TaroElement>

294

}

295

296

interface UpdatePayload {

297

path: string // Update path (dot notation)

298

value: any // New value

299

}

300

301

interface MpInstance {

302

setData(data: Record<string, any>, callback?: () => void): void

303

}

304

```

305

306

#### Key Features

307

308

- **Update Batching**: Collects multiple changes into single `setData` call

309

- **Callback Management**: Handles post-update callbacks

310

- **Custom Wrappers**: Manages platform-specific wrapper elements

311

- **Performance Optimization**: Minimizes mini-program update frequency

312

313

#### Usage Examples

314

315

```typescript

316

// Root element is created automatically by document

317

const root = document.getElementById('app')._root

318

319

// Manual update triggering (usually automatic)

320

root.enqueueUpdate()

321

322

// Add update callback

323

root.enqueueUpdateCallback(() => {

324

console.log('Update completed')

325

})

326

327

// Schedule async task

328

root.scheduleTask(() => {

329

// Task executed after current update cycle

330

console.log('Async task executed')

331

})

332

333

// Access mini-program context

334

if (root.ctx) {

335

root.ctx.setData({ customData: 'value' })

336

}

337

```

338

339

## Style Management

340

341

### Style

342

343

```typescript { .api }

344

import { Style } from '@tarojs/runtime'

345

346

class Style {

347

// Properties

348

cssText: string // Complete CSS text

349

350

// Property methods

351

setProperty(property: string, value: string | null, priority?: string): void

352

removeProperty(property: string): void

353

getPropertyValue(property: string): string

354

355

// Direct property access (camelCase)

356

[property: string]: string

357

}

358

```

359

360

#### Key Features

361

362

- **CSS Property Validation**: Validates CSS property names and values

363

- **CSS Variables**: Supports custom properties (--variable-name)

364

- **Webkit Prefixes**: Handles -webkit- prefixed properties

365

- **CamelCase Conversion**: Converts kebab-case to camelCase automatically

366

367

#### Usage Examples

368

369

```typescript

370

const element = document.createElement('view')

371

372

// Set individual properties

373

element.style.setProperty('background-color', '#ffffff')

374

element.style.setProperty('font-size', '16px')

375

element.style.setProperty('--custom-color', '#ff0000')

376

377

// Direct property access (camelCase)

378

element.style.backgroundColor = '#000000'

379

element.style.fontSize = '18px'

380

element.style.marginTop = '10px'

381

382

// Get property values

383

console.log('Background:', element.style.getPropertyValue('background-color'))

384

console.log('Font size:', element.style.fontSize)

385

386

// Remove properties

387

element.style.removeProperty('margin-top')

388

389

// Set multiple properties via cssText

390

element.style.cssText = 'color: red; padding: 8px; border: 1px solid #ccc;'

391

392

// Get complete CSS

393

console.log('All styles:', element.style.cssText)

394

```

395

396

### ClassList

397

398

```typescript { .api }

399

import { ClassList } from '@tarojs/runtime'

400

401

class ClassList {

402

// Properties

403

readonly length: number // Number of classes

404

405

// Methods

406

add(...classNames: string[]): void

407

remove(...classNames: string[]): void

408

toggle(className: string, force?: boolean): boolean

409

contains(className: string): boolean

410

411

// Iteration

412

item(index: number): string | null

413

toString(): string

414

415

// Array-like access

416

[index: number]: string

417

}

418

```

419

420

#### Usage Examples

421

422

```typescript

423

const element = document.createElement('view')

424

425

// Add classes

426

element.classList.add('container')

427

element.classList.add('active', 'visible')

428

429

// Remove classes

430

element.classList.remove('active')

431

432

// Toggle classes

433

element.classList.toggle('hidden') // Add if not present

434

element.classList.toggle('visible', false) // Force remove

435

436

// Check for classes

437

if (element.classList.contains('container')) {

438

console.log('Element is a container')

439

}

440

441

// Access by index

442

console.log('First class:', element.classList[0]) // "container"

443

console.log('Class count:', element.classList.length) // 2

444

445

// Convert to string

446

console.log('Classes:', element.classList.toString()) // "container visible"

447

```

448

449

## Event System

450

451

### TaroEvent

452

453

```typescript { .api }

454

import { TaroEvent, createEvent } from '@tarojs/runtime'

455

456

interface TaroEvent extends Event {

457

// Standard Event properties

458

type: string // Event type

459

bubbles: boolean // Whether event bubbles

460

cancelable: boolean // Whether event can be canceled

461

target: TaroElement // Event target

462

currentTarget: TaroElement // Current event handler element

463

timeStamp: number // Event timestamp

464

465

// Mini-program integration

466

mpEvent?: any // Original mini-program event

467

468

// Event control

469

stopPropagation(): void

470

stopImmediatePropagation(): void

471

preventDefault(): void

472

473

// State

474

readonly defaultPrevented: boolean

475

readonly eventPhase: number

476

}

477

478

// Event creation

479

function createEvent(event: any, node?: TaroElement): TaroEvent

480

```

481

482

#### Key Features

483

484

- **Event Bubbling**: Simulates web-style event bubbling on mini-programs

485

- **Dataset Merging**: Automatically merges `dataset` attributes into event

486

- **Batch Processing**: Optimizes event handling with batched updates

487

- **Cross-platform**: Works identically on web and mini-program platforms

488

489

#### Usage Examples

490

491

```typescript

492

// Event handler

493

function handleTap(event: TaroEvent) {

494

console.log('Event type:', event.type) // "tap"

495

console.log('Target element:', event.target) // Tapped element

496

console.log('Current target:', event.currentTarget) // Handler element

497

console.log('Timestamp:', event.timeStamp) // Event time

498

499

// Access mini-program event data

500

if (event.mpEvent) {

501

console.log('Touch data:', event.mpEvent.touches)

502

}

503

504

// Control event propagation

505

event.stopPropagation() // Stop bubbling

506

event.preventDefault() // Cancel default action

507

}

508

509

// Add event listeners

510

element.addEventListener('tap', handleTap)

511

element.addEventListener('longpress', (event) => {

512

console.log('Long press detected')

513

})

514

515

// Create custom events

516

const customEvent = createEvent({

517

type: 'custom',

518

detail: { customData: 'value' }

519

}, element)

520

521

// Dispatch events

522

element.dispatchEvent(customEvent)

523

```

524

525

### Event Handler

526

527

```typescript { .api }

528

import { eventHandler } from '@tarojs/runtime'

529

530

function eventHandler(handler: (event: TaroEvent) => void): (mpEvent: any) => void

531

```

532

533

The `eventHandler` function wraps standard event handlers to work with mini-program events:

534

535

```typescript

536

// Standard handler (receives TaroEvent)

537

function onTap(event: TaroEvent) {

538

console.log('Tapped:', event.target.tagName)

539

}

540

541

// Wrap for mini-program use

542

const mpHandler = eventHandler(onTap)

543

544

// Use in mini-program component

545

{

546

data: {},

547

onTap: mpHandler // Automatically converts mpEvent to TaroEvent

548

}

549

```

550

551

### EventSource

552

553

```typescript { .api }

554

import { eventSource } from '@tarojs/runtime'

555

556

interface EventSource {

557

// Global event registry for DOM nodes

558

set(node: TaroNode, event: TaroEvent): void

559

get(node: TaroNode): TaroEvent | null

560

delete(node: TaroNode): void

561

}

562

```

563

564

## Form Elements

565

566

### FormElement

567

568

```typescript { .api }

569

import { FormElement } from '@tarojs/runtime'

570

571

class FormElement extends TaroElement {

572

// Form-specific properties

573

type: string // Input type

574

value: string // Current value

575

576

// Automatic value synchronization on input/change events

577

}

578

```

579

580

#### Usage Examples

581

582

```typescript

583

// Create form elements

584

const input = document.createElement('input')

585

input.type = 'text'

586

input.value = 'Initial value'

587

588

const textarea = document.createElement('textarea')

589

textarea.value = 'Multi-line text'

590

591

// Value updates automatically sync with mini-program

592

input.addEventListener('input', (event) => {

593

console.log('New value:', input.value)

594

})

595

596

// Form submission

597

const form = document.createElement('form')

598

form.appendChild(input)

599

form.addEventListener('submit', (event) => {

600

event.preventDefault()

601

console.log('Form data:', input.value)

602

})

603

```

604

605

## SVG Support

606

607

### SVGElement

608

609

```typescript { .api }

610

import { SVGElement } from '@tarojs/runtime'

611

612

class SVGElement extends TaroElement {

613

// SVG-specific implementation

614

// Inherits all TaroElement functionality with SVG namespace handling

615

}

616

```

617

618

#### Usage Examples

619

620

```typescript

621

// Create SVG elements

622

const svg = document.createElement('svg')

623

svg.setAttribute('width', '100')

624

svg.setAttribute('height', '100')

625

626

const circle = document.createElement('circle')

627

circle.setAttribute('cx', '50')

628

circle.setAttribute('cy', '50')

629

circle.setAttribute('r', '25')

630

circle.setAttribute('fill', 'blue')

631

632

svg.appendChild(circle)

633

```

634

635

## Mutation Observer

636

637

### MutationObserver

638

639

```typescript { .api }

640

import { MutationObserver } from '@tarojs/runtime'

641

642

class MutationObserver {

643

constructor(callback: MutationCallback)

644

645

// Observation control

646

observe(target: Node, options?: MutationObserverInit): void

647

disconnect(): void

648

takeRecords(): MutationRecord[]

649

}

650

651

interface MutationRecord {

652

type: 'attributes' | 'characterData' | 'childList'

653

target: Node

654

addedNodes: NodeList

655

removedNodes: NodeList

656

previousSibling: Node | null

657

nextSibling: Node | null

658

attributeName: string | null

659

attributeNamespace: string | null

660

oldValue: string | null

661

}

662

663

type MutationCallback = (mutations: MutationRecord[], observer: MutationObserver) => void

664

```

665

666

#### Usage Examples

667

668

```typescript

669

// Create observer

670

const observer = new MutationObserver((mutations) => {

671

mutations.forEach((mutation) => {

672

console.log('Mutation type:', mutation.type)

673

console.log('Target:', mutation.target)

674

675

if (mutation.type === 'childList') {

676

console.log('Added nodes:', mutation.addedNodes.length)

677

console.log('Removed nodes:', mutation.removedNodes.length)

678

}

679

680

if (mutation.type === 'attributes') {

681

console.log('Attribute changed:', mutation.attributeName)

682

}

683

})

684

})

685

686

// Start observing

687

observer.observe(document.body, {

688

childList: true, // Watch for child additions/removals

689

attributes: true, // Watch for attribute changes

690

characterData: true, // Watch for text content changes

691

subtree: true // Watch entire subtree

692

})

693

694

// Stop observing

695

observer.disconnect()

696

697

// Get pending mutations

698

const mutations = observer.takeRecords()

699

```

700

701

## Platform-Specific Optimizations

702

703

### Component Aliasing

704

705

Elements are automatically mapped to platform-specific components:

706

707

```typescript

708

// Generic element

709

const view = document.createElement('view')

710

711

// Platform-specific mapping:

712

// Web: <div>

713

// WeChat: <view>

714

// Alipay: <view>

715

// etc.

716

```

717

718

### View Optimization

719

720

Special view types for performance optimization:

721

722

```typescript

723

// Performance-optimized views

724

const pureView = document.createElement('pure-view') // Static content

725

const staticView = document.createElement('static-view') // No event handling

726

const catchView = document.createElement('catch-view') // Catch touch events

727

const clickView = document.createElement('click-view') // Click-only events

728

```

729

730

### Update Optimization

731

732

The DOM uses path-based updates for efficient mini-program rendering:

733

734

```typescript

735

// Automatic path-based updates

736

const element = document.createElement('view')

737

element.textContent = 'Hello' // Updates: { "root.cn.[0].v": "Hello" }

738

739

element.style.color = 'red' // Updates: { "root.cn.[0].st.color": "red" }

740

```

741

742

The DOM implementation provides complete web compatibility while optimizing for mini-program performance, enabling seamless cross-platform development.