Cross-platform runtime for Taro framework providing DOM/BOM polyfills and mini-program bridge functionality
—
Complete browser API polyfills that enable web-like development on mini-program platforms. The BOM implementation provides familiar browser objects including document, window, history, location, and navigation APIs.
The BOM module creates a standardized browser environment across all platforms by implementing:
import { document, TaroDocument } from '@tarojs/runtime'
interface TaroDocument extends TaroElement {
// Element creation
createElement(tagName: string): TaroElement
createTextNode(data: string): TaroText
createComment(data: string): TaroText
// Element selection
getElementById(id: string): TaroElement | null
querySelector(selectors: string): TaroElement | null
querySelectorAll(selectors: string): TaroElement[]
// Properties
documentElement: TaroElement // <html> element
head: TaroElement // <head> element
body: TaroElement // <body> element
// Event handling
addEventListener(type: string, handler: EventListener): void
removeEventListener(type: string, handler: EventListener): void
}The document creates a standard HTML structure:
<html>
<head/>
<body>
<container>
<app/>
</container>
</body>
</html>// Create elements
const view = document.createElement('view')
const text = document.createTextNode('Hello World')
view.appendChild(text)
// Find elements
const app = document.getElementById('app')
const container = document.querySelector('.container')
const views = document.querySelectorAll('view')
// Modify document
document.body.appendChild(view)
document.documentElement.className = 'theme-dark'import { window, TaroWindow } from '@tarojs/runtime'
interface TaroWindow extends Events {
// Navigation objects
navigator: Navigator
location: TaroLocation
history: TaroHistory
// Timing functions
setTimeout(handler: TimerHandler, timeout?: number, ...args: any[]): number
clearTimeout(handle?: number): void
setInterval(handler: TimerHandler, timeout?: number, ...args: any[]): number
clearInterval(handle?: number): void
// Animation
requestAnimationFrame(callback: FrameRequestCallback): number
cancelAnimationFrame(handle: number): void
// Styles
getComputedStyle(element: Element, pseudoElt?: string | null): CSSStyleDeclaration
// Standard objects
Date: DateConstructor
XMLHttpRequest: any
// Event handling (inherited from Events)
addEventListener(type: string, handler: EventListener): void
removeEventListener(type: string, handler: EventListener): void
// Context management (internal)
CONTEXT_ACTIONS: typeof CONTEXT_ACTIONS
}
enum CONTEXT_ACTIONS {
INIT = '0', // Initialize new page context
RESTORE = '1', // Restore existing context
RECOVER = '2', // Recover from cached context
DESTORY = '3' // Destroy context on page unload
}// Timer functions
const timerId = window.setTimeout(() => {
console.log('Delayed execution')
}, 1000)
const intervalId = window.setInterval(() => {
console.log('Periodic execution')
}, 500)
window.clearTimeout(timerId)
window.clearInterval(intervalId)
// Animation frame
window.requestAnimationFrame((timestamp) => {
// Animation logic
console.log('Frame at:', timestamp)
})
// Event handling
window.addEventListener('resize', () => {
console.log('Window resized')
})
// Get computed styles
const styles = window.getComputedStyle(element)
console.log(styles.color, styles.fontSize)import { History, TaroHistory } from '@tarojs/runtime'
interface TaroHistory extends Events {
// Properties
readonly length: number
readonly state: any
// Navigation methods
back(): void
forward(): void
go(delta?: number): void
// State management
pushState(stateObj: any, title: string, url?: string | null): void
replaceState(stateObj: any, title: string, url?: string | null): void
// Event handling
addEventListener(type: 'popstate', handler: (event: PopStateEvent) => void): void
removeEventListener(type: 'popstate', handler: (event: PopStateEvent) => void): void
}
// Global history instance
const history: TaroHistorypopstate events for navigation changes// Navigation
history.back() // Go back one step
history.forward() // Go forward one step
history.go(-2) // Go back 2 steps
history.go(1) // Go forward 1 step
// State management
history.pushState({ page: 1 }, 'Page 1', '/page1')
history.replaceState({ page: 2 }, 'Page 2', '/page2')
// Listen for navigation
history.addEventListener('popstate', (event) => {
console.log('Navigation state:', event.state)
console.log('History length:', history.length)
})
// Access current state
console.log('Current state:', history.state)
console.log('History entries:', history.length)import { Location, TaroLocation } from '@tarojs/runtime'
interface TaroLocation {
// URL components
protocol: string // "https:"
host: string // "example.com:8080"
hostname: string // "example.com"
port: string // "8080"
pathname: string // "/path/to/page"
search: string // "?param=value"
hash: string // "#section"
href: string // Full URL
origin: string // "https://example.com:8080"
// Navigation methods
assign(url: string): void
replace(url: string): void
reload(): void
toString(): string
}
// Global location instance
const location: TaroLocationhashchange events// Read URL components
console.log('Current page:', location.pathname)
console.log('Query params:', location.search)
console.log('Hash fragment:', location.hash)
console.log('Full URL:', location.href)
// Navigation
location.assign('/new-page') // Navigate to new page (adds history entry)
location.replace('/replacement') // Replace current page (no history entry)
location.reload() // Reload current page
// URL manipulation
location.hash = '#new-section' // Update hash
location.search = '?param=value' // Update query params
// Listen for hash changes
window.addEventListener('hashchange', () => {
console.log('Hash changed to:', location.hash)
})import { navigator } from '@tarojs/runtime'
interface Navigator {
readonly appCodeName: string // "Mozilla"
readonly appName: string // "Netscape"
readonly appVersion: string // Version string
readonly cookieEnabled: boolean // true
readonly onLine: boolean // true
readonly platform: string // "MacIntel"
readonly product: string // "Gecko"
readonly productSub: string // "20030107"
readonly userAgent: string // User agent string
readonly vendor: string // "Google Inc."
readonly vendorSub: string // ""
}// Detect platform/browser
console.log('Platform:', navigator.platform)
console.log('User Agent:', navigator.userAgent)
console.log('Online status:', navigator.onLine)
// Feature detection
if (navigator.cookieEnabled) {
// Cookies are supported
}
// App information
console.log('App name:', navigator.appName)
console.log('App version:', navigator.appVersion)import { URL, TaroURL } from '@tarojs/runtime'
interface TaroURL {
// URL components
protocol: string
hostname: string
host: string
port: string
pathname: string
search: string
hash: string
href: string
origin: string
// Search parameters
searchParams: URLSearchParams
// Methods
toString(): string
toJSON(): string
// Static methods (throw in mini-programs)
static createObjectURL(object: any): string
static revokeObjectURL(url: string): void
}
// Constructor
new URL(url: string, base?: string | URL): TaroURL// Parse URL
const url = new URL('https://example.com:8080/path?param=value#section')
console.log('Protocol:', url.protocol) // "https:"
console.log('Host:', url.host) // "example.com:8080"
console.log('Pathname:', url.pathname) // "/path"
console.log('Search:', url.search) // "?param=value"
console.log('Hash:', url.hash) // "#section"
// Manipulate URL
url.pathname = '/new-path'
url.searchParams.set('newParam', 'newValue')
url.hash = '#new-section'
console.log('Updated URL:', url.toString())
// Relative URLs
const relative = new URL('/relative', 'https://example.com')
console.log('Absolute URL:', relative.href)import { URLSearchParams } from '@tarojs/runtime'
interface URLSearchParams {
// Manipulation methods
append(name: string, value: string): void
delete(name: string): void
get(name: string): string | null
getAll(name: string): string[]
has(name: string): boolean
set(name: string, value: string): void
// Iteration
keys(): IterableIterator<string>
values(): IterableIterator<string>
entries(): IterableIterator<[string, string]>
forEach(callback: (value: string, key: string, parent: URLSearchParams) => void): void
// Serialization
toString(): string
}
// Constructor
new URLSearchParams(init?: string | URLSearchParams | Record<string, string>): URLSearchParams// Create from string
const params = new URLSearchParams('?name=John&age=30&hobby=reading&hobby=gaming')
// Basic operations
console.log('Name:', params.get('name')) // "John"
console.log('All hobbies:', params.getAll('hobby')) // ["reading", "gaming"]
console.log('Has email:', params.has('email')) // false
// Modify parameters
params.set('age', '31') // Update existing
params.append('hobby', 'cooking') // Add new value
params.delete('name') // Remove parameter
// Iterate over parameters
params.forEach((value, key) => {
console.log(`${key}: ${value}`)
})
for (const [key, value] of params.entries()) {
console.log(`${key} = ${value}`)
}
// Convert to string
console.log('Query string:', params.toString()) // "age=31&hobby=reading&hobby=gaming&hobby=cooking"import { requestAnimationFrame, cancelAnimationFrame, now } from '@tarojs/runtime'
// Animation frame scheduling
function requestAnimationFrame(callback: FrameRequestCallback): number
function cancelAnimationFrame(handle: number): void
// High-resolution timestamp
function now(): number
type FrameRequestCallback = (timestamp: number) => voidrequestAnimationFrame on web, setTimeout fallback on mini-programsnow()// Basic animation
function animate(timestamp: number) {
// Animation logic here
console.log('Frame at:', timestamp)
// Continue animation
requestAnimationFrame(animate)
}
// Start animation
const animationId = requestAnimationFrame(animate)
// Cancel animation
cancelAnimationFrame(animationId)
// Performance timing
const start = now()
// ... some work
const duration = now() - start
console.log('Operation took:', duration, 'ms')
// Smooth animation with timing
let startTime: number | null = null
function step(timestamp: number) {
if (!startTime) startTime = timestamp
const progress = (timestamp - startTime) / 1000 // 1 second animation
if (progress < 1) {
// Update animation state based on progress
updateAnimation(progress)
requestAnimationFrame(step)
} else {
// Animation complete
finishAnimation()
}
}
requestAnimationFrame(step)import { getComputedStyle } from '@tarojs/runtime'
function getComputedStyle(
element: Element,
pseudoElement?: string | null
): CSSStyleDeclaration
interface CSSStyleDeclaration {
[property: string]: string
cssText: string
length: number
// Property access methods
getPropertyValue(property: string): string
setProperty(property: string, value: string, priority?: string): void
removeProperty(property: string): string
}// Get computed styles
const element = document.getElementById('my-element')
const styles = getComputedStyle(element)
// Access individual properties
console.log('Color:', styles.color)
console.log('Font size:', styles.fontSize)
console.log('Display:', styles.display)
// Access via getPropertyValue
console.log('Background:', styles.getPropertyValue('background-color'))
// Get all CSS text
console.log('All styles:', styles.cssText)
// Pseudo-element styles (web only)
const beforeStyles = getComputedStyle(element, '::before')
console.log('Before content:', beforeStyles.content)Some browser APIs have limitations on mini-program platforms:
// These throw errors on mini-programs
try {
URL.createObjectURL(blob) // Not supported
URL.revokeObjectURL(url) // Not supported
} catch (error) {
console.log('Not available on mini-programs')
}
// Fallback implementations
const styles = getComputedStyle(element) // Falls back to element.style
const timestamp = now() // Uses Date.now() if performance API unavailableThe window object manages page contexts automatically:
// Context actions (internal use)
window.CONTEXT_ACTIONS.INIT // Initialize new page
window.CONTEXT_ACTIONS.RESTORE // Restore cached page
window.CONTEXT_ACTIONS.RECOVER // Recover from cache
window.CONTEXT_ACTIONS.DESTORY // Clean up page contextThe BOM APIs provide a complete browser environment that enables seamless cross-platform development while maintaining optimal performance on each target platform.
Install with Tessl CLI
npx tessl i tessl/npm-tarojs--runtime