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.