Cross-platform runtime for Taro framework providing DOM/BOM polyfills and mini-program bridge functionality
—
DSL (Domain Specific Language) functions for integrating React components with mini-program platforms, including page configuration, component lifecycle management, and instance handling.
The framework integration module provides the bridge between React components and mini-program platforms by:
import { createPageConfig } from '@tarojs/runtime'
function createPageConfig(
component: ComponentClass,
pageName?: string,
data?: Record<string, any>,
pageConfig?: PageConfig
): PageInstance
interface PageConfig {
navigationBarTitleText?: string
navigationBarBackgroundColor?: string
navigationBarTextStyle?: 'black' | 'white'
backgroundColor?: string
backgroundTextStyle?: 'dark' | 'light'
enablePullDownRefresh?: boolean
onReachBottomDistance?: number
[key: string]: any
}
interface PageInstance {
// Page data
data: Record<string, any>
// Lifecycle methods
onLoad?(options: Record<string, unknown>): void
onShow?(): void
onHide?(): void
onReady?(): void
onUnload?(): void
onPullDownRefresh?(): void
onReachBottom?(): void
onPageScroll?(event: { scrollTop: number }): void
onShareAppMessage?(event: any): any
onShareTimeline?(): any
// Custom methods
[key: string]: any
}// Basic page configuration
class HomePage extends React.Component {
state = { count: 0 }
onIncrement = () => {
this.setState({ count: this.state.count + 1 })
}
render() {
return (
<View onClick={this.onIncrement}>
Count: {this.state.count}
</View>
)
}
}
// Create mini-program page config
const pageConfig = createPageConfig(
HomePage,
'home',
{ title: 'Home Page' },
{
navigationBarTitleText: 'Home',
enablePullDownRefresh: true
}
)
// Advanced page with lifecycle
class UserProfile extends React.Component {
componentDidMount() {
// Automatically called during onReady
this.loadUserData()
}
onPullDownRefresh() {
// Mini-program pull refresh handler
this.refreshData().then(() => {
wx.stopPullDownRefresh()
})
}
onShareAppMessage() {
return {
title: 'Check out my profile',
path: '/pages/profile/profile'
}
}
loadUserData = async () => {
const userData = await api.getUserProfile()
this.setState({ user: userData })
}
refreshData = async () => {
await this.loadUserData()
// Update UI after data refresh
}
render() {
return <UserProfileView user={this.state.user} />
}
}
const profileConfig = createPageConfig(
UserProfile,
'profile',
{ user: null },
{
navigationBarTitleText: 'Profile',
enablePullDownRefresh: true,
backgroundColor: '#f5f5f5'
}
)import { createComponentConfig } from '@tarojs/runtime'
function createComponentConfig(config: ComponentConfig): ComponentInstance
interface ComponentConfig {
// Lifecycle methods
attached?(): void // Component attached to DOM
detached?(): void // Component removed from DOM
ready?(): void // Component ready (after attached)
moved?(): void // Component moved in DOM
// Data and methods
data?: Record<string, any>
methods?: Record<string, Function>
// Component options
options?: {
multipleSlots?: boolean
addGlobalClass?: boolean
virtualHost?: boolean
}
// Relations (component communication)
relations?: Record<string, RelationConfig>
// Observers (data watchers)
observers?: Record<string, Function>
// External classes
externalClasses?: string[]
}
interface ComponentInstance {
data: Record<string, any>
setData(data: Record<string, any>, callback?: () => void): void
// Lifecycle methods
attached?(): void
detached?(): void
ready?(): void
moved?(): void
// Custom methods
[key: string]: any
}// Basic component configuration
const buttonComponent = createComponentConfig({
data: {
text: '',
disabled: false
},
methods: {
onTap() {
if (!this.data.disabled) {
this.triggerEvent('tap', { value: this.data.text })
}
}
},
attached() {
console.log('Button component attached')
},
detached() {
console.log('Button component detached')
}
})
// Advanced component with relations
const listComponent = createComponentConfig({
data: {
items: []
},
relations: {
'./list-item': {
type: 'child',
linked(target) {
// Child list-item component linked
this.data.items.push(target)
},
unlinked(target) {
// Child list-item component unlinked
const index = this.data.items.indexOf(target)
this.data.items.splice(index, 1)
}
}
},
observers: {
'items.length': function(newLength) {
console.log('Items count changed:', newLength)
}
},
options: {
multipleSlots: true,
addGlobalClass: true
},
externalClasses: ['custom-class'],
ready() {
// Component ready for interaction
this.updateItemsData()
}
})import { createRecursiveComponentConfig } from '@tarojs/runtime'
function createRecursiveComponentConfig(config?: RecursiveConfig): ComponentInstance
interface RecursiveConfig {
// Custom wrapper handling
customWrapper?: boolean
// Virtual host options
virtualHost?: boolean
}// Recursive component for tree structures
const treeComponent = createRecursiveComponentConfig({
customWrapper: true,
virtualHost: true
})
// Use in dynamic component rendering
const dynamicRenderer = createRecursiveComponentConfig()import {
getPageInstance,
injectPageInstance,
removePageInstance
} from '@tarojs/runtime'
// Get page instance by ID
function getPageInstance(id: string): PageInstance | undefined
// Register page instance
function injectPageInstance(instance: PageInstance, id: string): void
// Unregister page instance
function removePageInstance(id: string): void// Register page instance
const pageId = 'home-page-123'
injectPageInstance(homePageConfig, pageId)
// Retrieve page instance
const instance = getPageInstance(pageId)
if (instance) {
// Access page data and methods
console.log('Page data:', instance.data)
instance.onShow?.()
}
// Clean up page instance
removePageInstance(pageId)import { getCurrentInstance, Current } from '@tarojs/runtime'
// Get current runtime instance
function getCurrentInstance(): Current
interface Current {
app: AppInstance | null // Current app instance
router: Router | null // Current router state
page: PageInstance | null // Current page instance
preloadData?: any // Preloaded data
}
interface Router {
params: Record<string, unknown> // Route parameters
path: string // Current route path
$taroPath: string // Taro-specific path
onReady: string // Ready event key
onHide: string // Hide event key
onShow: string // Show event key
exitState?: any // Page exit state
}// Get current runtime state
const current = getCurrentInstance()
// Access current page
if (current.page) {
console.log('Current page data:', current.page.data)
// Call page methods
current.page.onShow?.()
}
// Access router information
if (current.router) {
console.log('Current path:', current.router.path)
console.log('Route params:', current.router.params)
console.log('Taro path:', current.router.$taroPath)
}
// Access app instance
if (current.app) {
console.log('App instance:', current.app)
}
// Access preloaded data
if (current.preloadData) {
console.log('Preloaded data:', current.preloadData)
}
// React hook usage
function useCurrentInstance() {
return getCurrentInstance()
}
// Component usage
function MyComponent() {
const current = useCurrentInstance()
useEffect(() => {
console.log('Current router:', current.router)
}, [current.router])
return <div>Path: {current.router?.path}</div>
}import {
getOnReadyEventKey,
getOnShowEventKey,
getOnHideEventKey
} from '@tarojs/runtime'
// Generate unique event keys for page lifecycle
function getOnReadyEventKey(id: string): string
function getOnShowEventKey(id: string): string
function getOnHideEventKey(id: string): stringconst pageId = 'user-profile'
// Generate lifecycle event keys
const readyKey = getOnReadyEventKey(pageId) // "onReady_user-profile"
const showKey = getOnShowEventKey(pageId) // "onShow_user-profile"
const hideKey = getOnHideEventKey(pageId) // "onHide_user-profile"
// Use in event registration
eventCenter.on(readyKey, () => {
console.log('Page ready:', pageId)
})
eventCenter.on(showKey, () => {
console.log('Page shown:', pageId)
})
eventCenter.on(hideKey, () => {
console.log('Page hidden:', pageId)
})import { safeExecute } from '@tarojs/runtime'
function safeExecute(
fn: Function | undefined,
context?: any,
...args: any[]
): anySafely executes lifecycle methods with error handling:
// Safe lifecycle execution
const pageInstance = getPageInstance('home')
// Safely call lifecycle methods
safeExecute(pageInstance?.onShow, pageInstance)
safeExecute(pageInstance?.onHide, pageInstance)
// With arguments
safeExecute(pageInstance?.onLoad, pageInstance, { id: '123' })
// Custom context
safeExecute(customMethod, customContext, arg1, arg2)import { stringify } from '@tarojs/runtime'
function stringify(data: any): stringSafely converts data to JSON string:
// Safe JSON stringification
const data = { name: 'John', age: 30, circular: null }
data.circular = data // Circular reference
const json = stringify(data) // Handles circular references
console.log('JSON:', json)
// Complex objects
const complexData = {
date: new Date(),
regex: /pattern/g,
fn: function() { return 'test' },
symbol: Symbol('test')
}
const safeJson = stringify(complexData) // Safely serializesimport { getPath } from '@tarojs/runtime'
function getPath(node: TaroElement): stringGets the dot-notation path for DOM updates:
// Get element path for updates
const element = document.getElementById('my-element')
const path = getPath(element) // "root.cn.[0].cn.[2]"
// Use in manual updates
const rootElement = element._root
rootElement.ctx?.setData({
[path + '.v']: 'new value'
})The framework automatically handles page context switching:
// Automatic context management
class MultiPageApp {
// Page A
pageA = createPageConfig(PageAComponent, 'pageA', {
// Page A state preserved automatically
userData: null
})
// Page B
pageB = createPageConfig(PageBComponent, 'pageB', {
// Page B state preserved automatically
settings: {}
})
}
// Context is automatically:
// 1. Saved when page hides (onHide)
// 2. Restored when page shows (onShow)
// 3. Cleaned up when page unloads (onUnload)// Custom lifecycle integration
class CustomLifecyclePage extends React.Component {
// Standard React lifecycle
componentDidMount() {
// Called during mini-program onReady
}
componentWillUnmount() {
// Called during mini-program onUnload
}
// Mini-program specific lifecycle
onPullDownRefresh() {
// Handle pull-to-refresh
}
onReachBottom() {
// Handle scroll to bottom
}
onPageScroll(event) {
// Handle page scroll
console.log('Scroll position:', event.scrollTop)
}
onShareAppMessage(event) {
// Handle share action
return {
title: 'Share title',
path: '/pages/share/share'
}
}
}// Parent-child component communication
const parentConfig = createComponentConfig({
data: { message: 'Hello from parent' },
methods: {
sendToChild(data) {
// Send data to child component
this.selectComponent('#child').receiveFromParent(data)
},
receiveFromChild(event) {
// Receive data from child component
console.log('Child sent:', event.detail)
}
}
})
const childConfig = createComponentConfig({
data: { childData: 'Hello from child' },
methods: {
sendToParent() {
// Send data to parent component
this.triggerEvent('childEvent', {
message: this.data.childData
})
},
receiveFromParent(data) {
// Receive data from parent
this.setData({ parentMessage: data })
}
}
})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.
Install with Tessl CLI
npx tessl i tessl/npm-tarojs--runtime