or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

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

framework-integration.mddocs/

0

# Framework Integration APIs

1

2

DSL (Domain Specific Language) functions for integrating React components with mini-program platforms, including page configuration, component lifecycle management, and instance handling.

3

4

## Overview

5

6

The framework integration module provides the bridge between React components and mini-program platforms by:

7

8

- **Page Configuration**: Converting React components into mini-program pages

9

- **Component Configuration**: Creating mini-program component definitions

10

- **Lifecycle Management**: Handling page and component lifecycle events

11

- **Instance Registry**: Managing page and component instances

12

- **Context Switching**: Automatic state management for multi-page applications

13

- **Recursive Components**: Dynamic component rendering support

14

15

## Page Configuration

16

17

### createPageConfig

18

19

```typescript { .api }

20

import { createPageConfig } from '@tarojs/runtime'

21

22

function createPageConfig(

23

component: ComponentClass,

24

pageName?: string,

25

data?: Record<string, any>,

26

pageConfig?: PageConfig

27

): PageInstance

28

29

interface PageConfig {

30

navigationBarTitleText?: string

31

navigationBarBackgroundColor?: string

32

navigationBarTextStyle?: 'black' | 'white'

33

backgroundColor?: string

34

backgroundTextStyle?: 'dark' | 'light'

35

enablePullDownRefresh?: boolean

36

onReachBottomDistance?: number

37

[key: string]: any

38

}

39

40

interface PageInstance {

41

// Page data

42

data: Record<string, any>

43

44

// Lifecycle methods

45

onLoad?(options: Record<string, unknown>): void

46

onShow?(): void

47

onHide?(): void

48

onReady?(): void

49

onUnload?(): void

50

onPullDownRefresh?(): void

51

onReachBottom?(): void

52

onPageScroll?(event: { scrollTop: number }): void

53

onShareAppMessage?(event: any): any

54

onShareTimeline?(): any

55

56

// Custom methods

57

[key: string]: any

58

}

59

```

60

61

#### Key Features

62

63

- **Lifecycle Integration**: Automatically maps React lifecycle to mini-program lifecycle

64

- **Context Switching**: Manages page context transitions and state preservation

65

- **Event Handling**: Binds component methods to mini-program page events

66

- **Data Synchronization**: Keeps React state in sync with mini-program data

67

68

#### Usage Examples

69

70

```typescript

71

// Basic page configuration

72

class HomePage extends React.Component {

73

state = { count: 0 }

74

75

onIncrement = () => {

76

this.setState({ count: this.state.count + 1 })

77

}

78

79

render() {

80

return (

81

<View onClick={this.onIncrement}>

82

Count: {this.state.count}

83

</View>

84

)

85

}

86

}

87

88

// Create mini-program page config

89

const pageConfig = createPageConfig(

90

HomePage,

91

'home',

92

{ title: 'Home Page' },

93

{

94

navigationBarTitleText: 'Home',

95

enablePullDownRefresh: true

96

}

97

)

98

99

// Advanced page with lifecycle

100

class UserProfile extends React.Component {

101

componentDidMount() {

102

// Automatically called during onReady

103

this.loadUserData()

104

}

105

106

onPullDownRefresh() {

107

// Mini-program pull refresh handler

108

this.refreshData().then(() => {

109

wx.stopPullDownRefresh()

110

})

111

}

112

113

onShareAppMessage() {

114

return {

115

title: 'Check out my profile',

116

path: '/pages/profile/profile'

117

}

118

}

119

120

loadUserData = async () => {

121

const userData = await api.getUserProfile()

122

this.setState({ user: userData })

123

}

124

125

refreshData = async () => {

126

await this.loadUserData()

127

// Update UI after data refresh

128

}

129

130

render() {

131

return <UserProfileView user={this.state.user} />

132

}

133

}

134

135

const profileConfig = createPageConfig(

136

UserProfile,

137

'profile',

138

{ user: null },

139

{

140

navigationBarTitleText: 'Profile',

141

enablePullDownRefresh: true,

142

backgroundColor: '#f5f5f5'

143

}

144

)

145

```

146

147

## Component Configuration

148

149

### createComponentConfig

150

151

```typescript { .api }

152

import { createComponentConfig } from '@tarojs/runtime'

153

154

function createComponentConfig(config: ComponentConfig): ComponentInstance

155

156

interface ComponentConfig {

157

// Lifecycle methods

158

attached?(): void // Component attached to DOM

159

detached?(): void // Component removed from DOM

160

ready?(): void // Component ready (after attached)

161

moved?(): void // Component moved in DOM

162

163

// Data and methods

164

data?: Record<string, any>

165

methods?: Record<string, Function>

166

167

// Component options

168

options?: {

169

multipleSlots?: boolean

170

addGlobalClass?: boolean

171

virtualHost?: boolean

172

}

173

174

// Relations (component communication)

175

relations?: Record<string, RelationConfig>

176

177

// Observers (data watchers)

178

observers?: Record<string, Function>

179

180

// External classes

181

externalClasses?: string[]

182

}

183

184

interface ComponentInstance {

185

data: Record<string, any>

186

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

187

188

// Lifecycle methods

189

attached?(): void

190

detached?(): void

191

ready?(): void

192

moved?(): void

193

194

// Custom methods

195

[key: string]: any

196

}

197

```

198

199

#### Usage Examples

200

201

```typescript

202

// Basic component configuration

203

const buttonComponent = createComponentConfig({

204

data: {

205

text: '',

206

disabled: false

207

},

208

209

methods: {

210

onTap() {

211

if (!this.data.disabled) {

212

this.triggerEvent('tap', { value: this.data.text })

213

}

214

}

215

},

216

217

attached() {

218

console.log('Button component attached')

219

},

220

221

detached() {

222

console.log('Button component detached')

223

}

224

})

225

226

// Advanced component with relations

227

const listComponent = createComponentConfig({

228

data: {

229

items: []

230

},

231

232

relations: {

233

'./list-item': {

234

type: 'child',

235

linked(target) {

236

// Child list-item component linked

237

this.data.items.push(target)

238

},

239

unlinked(target) {

240

// Child list-item component unlinked

241

const index = this.data.items.indexOf(target)

242

this.data.items.splice(index, 1)

243

}

244

}

245

},

246

247

observers: {

248

'items.length': function(newLength) {

249

console.log('Items count changed:', newLength)

250

}

251

},

252

253

options: {

254

multipleSlots: true,

255

addGlobalClass: true

256

},

257

258

externalClasses: ['custom-class'],

259

260

ready() {

261

// Component ready for interaction

262

this.updateItemsData()

263

}

264

})

265

```

266

267

### createRecursiveComponentConfig

268

269

```typescript { .api }

270

import { createRecursiveComponentConfig } from '@tarojs/runtime'

271

272

function createRecursiveComponentConfig(config?: RecursiveConfig): ComponentInstance

273

274

interface RecursiveConfig {

275

// Custom wrapper handling

276

customWrapper?: boolean

277

278

// Virtual host options

279

virtualHost?: boolean

280

}

281

```

282

283

#### Key Features

284

285

- **Dynamic Rendering**: Enables recursive component structures

286

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

287

- **Virtual Host**: Optimizes component hierarchy for performance

288

289

#### Usage Examples

290

291

```typescript

292

// Recursive component for tree structures

293

const treeComponent = createRecursiveComponentConfig({

294

customWrapper: true,

295

virtualHost: true

296

})

297

298

// Use in dynamic component rendering

299

const dynamicRenderer = createRecursiveComponentConfig()

300

```

301

302

## Instance Management

303

304

### Page Instance Registry

305

306

```typescript { .api }

307

import {

308

getPageInstance,

309

injectPageInstance,

310

removePageInstance

311

} from '@tarojs/runtime'

312

313

// Get page instance by ID

314

function getPageInstance(id: string): PageInstance | undefined

315

316

// Register page instance

317

function injectPageInstance(instance: PageInstance, id: string): void

318

319

// Unregister page instance

320

function removePageInstance(id: string): void

321

```

322

323

#### Usage Examples

324

325

```typescript

326

// Register page instance

327

const pageId = 'home-page-123'

328

injectPageInstance(homePageConfig, pageId)

329

330

// Retrieve page instance

331

const instance = getPageInstance(pageId)

332

if (instance) {

333

// Access page data and methods

334

console.log('Page data:', instance.data)

335

instance.onShow?.()

336

}

337

338

// Clean up page instance

339

removePageInstance(pageId)

340

```

341

342

### Current Instance

343

344

```typescript { .api }

345

import { getCurrentInstance, Current } from '@tarojs/runtime'

346

347

// Get current runtime instance

348

function getCurrentInstance(): Current

349

350

interface Current {

351

app: AppInstance | null // Current app instance

352

router: Router | null // Current router state

353

page: PageInstance | null // Current page instance

354

preloadData?: any // Preloaded data

355

}

356

357

interface Router {

358

params: Record<string, unknown> // Route parameters

359

path: string // Current route path

360

$taroPath: string // Taro-specific path

361

onReady: string // Ready event key

362

onHide: string // Hide event key

363

onShow: string // Show event key

364

exitState?: any // Page exit state

365

}

366

```

367

368

#### Usage Examples

369

370

```typescript

371

// Get current runtime state

372

const current = getCurrentInstance()

373

374

// Access current page

375

if (current.page) {

376

console.log('Current page data:', current.page.data)

377

378

// Call page methods

379

current.page.onShow?.()

380

}

381

382

// Access router information

383

if (current.router) {

384

console.log('Current path:', current.router.path)

385

console.log('Route params:', current.router.params)

386

console.log('Taro path:', current.router.$taroPath)

387

}

388

389

// Access app instance

390

if (current.app) {

391

console.log('App instance:', current.app)

392

}

393

394

// Access preloaded data

395

if (current.preloadData) {

396

console.log('Preloaded data:', current.preloadData)

397

}

398

399

// React hook usage

400

function useCurrentInstance() {

401

return getCurrentInstance()

402

}

403

404

// Component usage

405

function MyComponent() {

406

const current = useCurrentInstance()

407

408

useEffect(() => {

409

console.log('Current router:', current.router)

410

}, [current.router])

411

412

return <div>Path: {current.router?.path}</div>

413

}

414

```

415

416

## Lifecycle Event Keys

417

418

### Event Key Generators

419

420

```typescript { .api }

421

import {

422

getOnReadyEventKey,

423

getOnShowEventKey,

424

getOnHideEventKey

425

} from '@tarojs/runtime'

426

427

// Generate unique event keys for page lifecycle

428

function getOnReadyEventKey(id: string): string

429

function getOnShowEventKey(id: string): string

430

function getOnHideEventKey(id: string): string

431

```

432

433

#### Usage Examples

434

435

```typescript

436

const pageId = 'user-profile'

437

438

// Generate lifecycle event keys

439

const readyKey = getOnReadyEventKey(pageId) // "onReady_user-profile"

440

const showKey = getOnShowEventKey(pageId) // "onShow_user-profile"

441

const hideKey = getOnHideEventKey(pageId) // "onHide_user-profile"

442

443

// Use in event registration

444

eventCenter.on(readyKey, () => {

445

console.log('Page ready:', pageId)

446

})

447

448

eventCenter.on(showKey, () => {

449

console.log('Page shown:', pageId)

450

})

451

452

eventCenter.on(hideKey, () => {

453

console.log('Page hidden:', pageId)

454

})

455

```

456

457

## Utility Functions

458

459

### safeExecute

460

461

```typescript { .api }

462

import { safeExecute } from '@tarojs/runtime'

463

464

function safeExecute(

465

fn: Function | undefined,

466

context?: any,

467

...args: any[]

468

): any

469

```

470

471

Safely executes lifecycle methods with error handling:

472

473

```typescript

474

// Safe lifecycle execution

475

const pageInstance = getPageInstance('home')

476

477

// Safely call lifecycle methods

478

safeExecute(pageInstance?.onShow, pageInstance)

479

safeExecute(pageInstance?.onHide, pageInstance)

480

481

// With arguments

482

safeExecute(pageInstance?.onLoad, pageInstance, { id: '123' })

483

484

// Custom context

485

safeExecute(customMethod, customContext, arg1, arg2)

486

```

487

488

### stringify

489

490

```typescript { .api }

491

import { stringify } from '@tarojs/runtime'

492

493

function stringify(data: any): string

494

```

495

496

Safely converts data to JSON string:

497

498

```typescript

499

// Safe JSON stringification

500

const data = { name: 'John', age: 30, circular: null }

501

data.circular = data // Circular reference

502

503

const json = stringify(data) // Handles circular references

504

console.log('JSON:', json)

505

506

// Complex objects

507

const complexData = {

508

date: new Date(),

509

regex: /pattern/g,

510

fn: function() { return 'test' },

511

symbol: Symbol('test')

512

}

513

514

const safeJson = stringify(complexData) // Safely serializes

515

```

516

517

### getPath

518

519

```typescript { .api }

520

import { getPath } from '@tarojs/runtime'

521

522

function getPath(node: TaroElement): string

523

```

524

525

Gets the dot-notation path for DOM updates:

526

527

```typescript

528

// Get element path for updates

529

const element = document.getElementById('my-element')

530

const path = getPath(element) // "root.cn.[0].cn.[2]"

531

532

// Use in manual updates

533

const rootElement = element._root

534

rootElement.ctx?.setData({

535

[path + '.v']: 'new value'

536

})

537

```

538

539

## Advanced Integration Patterns

540

541

### Context Switching

542

543

The framework automatically handles page context switching:

544

545

```typescript

546

// Automatic context management

547

class MultiPageApp {

548

// Page A

549

pageA = createPageConfig(PageAComponent, 'pageA', {

550

// Page A state preserved automatically

551

userData: null

552

})

553

554

// Page B

555

pageB = createPageConfig(PageBComponent, 'pageB', {

556

// Page B state preserved automatically

557

settings: {}

558

})

559

}

560

561

// Context is automatically:

562

// 1. Saved when page hides (onHide)

563

// 2. Restored when page shows (onShow)

564

// 3. Cleaned up when page unloads (onUnload)

565

```

566

567

### Custom Lifecycle Hooks

568

569

```typescript

570

// Custom lifecycle integration

571

class CustomLifecyclePage extends React.Component {

572

// Standard React lifecycle

573

componentDidMount() {

574

// Called during mini-program onReady

575

}

576

577

componentWillUnmount() {

578

// Called during mini-program onUnload

579

}

580

581

// Mini-program specific lifecycle

582

onPullDownRefresh() {

583

// Handle pull-to-refresh

584

}

585

586

onReachBottom() {

587

// Handle scroll to bottom

588

}

589

590

onPageScroll(event) {

591

// Handle page scroll

592

console.log('Scroll position:', event.scrollTop)

593

}

594

595

onShareAppMessage(event) {

596

// Handle share action

597

return {

598

title: 'Share title',

599

path: '/pages/share/share'

600

}

601

}

602

}

603

```

604

605

### Component Communication

606

607

```typescript

608

// Parent-child component communication

609

const parentConfig = createComponentConfig({

610

data: { message: 'Hello from parent' },

611

612

methods: {

613

sendToChild(data) {

614

// Send data to child component

615

this.selectComponent('#child').receiveFromParent(data)

616

},

617

618

receiveFromChild(event) {

619

// Receive data from child component

620

console.log('Child sent:', event.detail)

621

}

622

}

623

})

624

625

const childConfig = createComponentConfig({

626

data: { childData: 'Hello from child' },

627

628

methods: {

629

sendToParent() {

630

// Send data to parent component

631

this.triggerEvent('childEvent', {

632

message: this.data.childData

633

})

634

},

635

636

receiveFromParent(data) {

637

// Receive data from parent

638

this.setData({ parentMessage: data })

639

}

640

}

641

})

642

```

643

644

The framework integration APIs provide a seamless bridge between React development patterns and mini-program platforms, enabling cross-platform development with familiar React concepts while leveraging platform-specific capabilities.