0
# Utilities & Performance APIs
1
2
Comprehensive utility functions, performance monitoring tools, event management, and optimization helpers for cross-platform Taro development.
3
4
## Overview
5
6
The utilities module provides essential tools for building performant cross-platform applications:
7
8
- **Performance Monitoring**: Timing, profiling, and performance measurement
9
- **Function Utilities**: Throttling, debouncing, and execution control
10
- **DOM Utilities**: Element type checking and manipulation helpers
11
- **Event Management**: Global event center and communication
12
- **Async Operations**: Next tick scheduling and update coordination
13
- **Hydration System**: DOM to mini-program data conversion
14
- **Router Utilities**: URL manipulation and navigation helpers
15
- **Cache Management**: Context-aware data caching
16
- **Options Configuration**: Runtime behavior configuration
17
18
## Performance APIs
19
20
### Performance Monitoring
21
22
```typescript { .api }
23
import { perf } from '@tarojs/runtime'
24
25
interface Performance {
26
// Timing methods
27
start(id: string): void
28
stop(id: string, now?: number): void
29
delayStop(id: string, delay?: number): void
30
31
// Internal timing storage
32
timers: Map<string, number>
33
}
34
35
const perf: Performance
36
```
37
38
#### Key Features
39
40
- **High-resolution Timing**: Uses `performance.now()` when available, falls back to `Date.now()`
41
- **Automatic Logging**: Logs timing results to console with formatted output
42
- **Delayed Stopping**: Debounced timing for frequent operations
43
- **Memory Management**: Automatic cleanup of completed timers
44
45
#### Usage Examples
46
47
```typescript
48
// Basic performance timing
49
perf.start('component-render')
50
// ... component rendering logic
51
perf.stop('component-render') // Logs: "component-render took X ms"
52
53
// Manual timing with custom timestamp
54
const startTime = performance.now()
55
// ... some operation
56
perf.stop('custom-operation', startTime)
57
58
// Delayed timing (debounced)
59
perf.start('frequent-operation')
60
perf.delayStop('frequent-operation', 100) // Waits 100ms before logging
61
62
// Multiple timing sessions
63
perf.start('data-fetch')
64
const data = await fetchData()
65
perf.stop('data-fetch')
66
67
perf.start('data-process')
68
const processed = processData(data)
69
perf.stop('data-process')
70
71
// Nested timing
72
perf.start('full-operation')
73
perf.start('sub-operation-1')
74
// ... work
75
perf.stop('sub-operation-1')
76
77
perf.start('sub-operation-2')
78
// ... more work
79
perf.stop('sub-operation-2')
80
perf.stop('full-operation')
81
```
82
83
## Function Utilities
84
85
### throttle
86
87
```typescript { .api }
88
import { throttle } from '@tarojs/runtime'
89
90
function throttle<T extends (...args: any[]) => any>(
91
fn: T,
92
threshold?: number,
93
scope?: any
94
): T
95
96
// Default threshold: 250ms
97
```
98
99
#### Key Features
100
101
- **Leading and Trailing**: Executes immediately and after threshold
102
- **Context Preservation**: Maintains `this` context when scope provided
103
- **Return Value**: Returns result of first execution during threshold period
104
105
#### Usage Examples
106
107
```typescript
108
// Basic throttling
109
const expensiveFunction = (data: string) => {
110
console.log('Processing:', data)
111
// Expensive computation
112
}
113
114
const throttledFn = throttle(expensiveFunction, 1000)
115
116
// Multiple rapid calls - only executes every 1000ms
117
throttledFn('call 1') // Executes immediately
118
throttledFn('call 2') // Ignored
119
throttledFn('call 3') // Ignored
120
// ... 1000ms later, executes with last arguments
121
122
// Scroll event throttling
123
const handleScroll = throttle((event: Event) => {
124
const scrollTop = (event.target as Element).scrollTop
125
console.log('Scroll position:', scrollTop)
126
}, 100)
127
128
window.addEventListener('scroll', handleScroll)
129
130
// Resize handler with context
131
class ResponsiveComponent {
132
threshold = 768
133
134
handleResize = throttle(function(this: ResponsiveComponent) {
135
if (window.innerWidth < this.threshold) {
136
this.enterMobileMode()
137
} else {
138
this.enterDesktopMode()
139
}
140
}, 250, this)
141
142
enterMobileMode() { /* ... */ }
143
enterDesktopMode() { /* ... */ }
144
}
145
```
146
147
### debounce
148
149
```typescript { .api }
150
import { debounce } from '@tarojs/runtime'
151
152
function debounce<T extends (...args: any[]) => any>(
153
fn: T,
154
ms?: number,
155
scope?: any
156
): T
157
158
// Default delay: 250ms
159
```
160
161
#### Key Features
162
163
- **Trailing Execution**: Only executes after delay period with no new calls
164
- **Context Preservation**: Maintains `this` context when scope provided
165
- **Cancellation**: Automatically cancels previous delayed executions
166
167
#### Usage Examples
168
169
```typescript
170
// Basic debouncing
171
const searchFunction = (query: string) => {
172
console.log('Searching for:', query)
173
// API call
174
}
175
176
const debouncedSearch = debounce(searchFunction, 500)
177
178
// Rapid typing - only searches after 500ms of no input
179
debouncedSearch('a') // Cancelled
180
debouncedSearch('ap') // Cancelled
181
debouncedSearch('app') // Cancelled
182
debouncedSearch('apple') // Executes after 500ms
183
184
// Form validation
185
const validateForm = debounce((formData: FormData) => {
186
// Validate form fields
187
console.log('Validating form...')
188
}, 300)
189
190
// API call debouncing
191
const saveData = debounce(async (data: any) => {
192
try {
193
await api.saveUserData(data)
194
console.log('Data saved successfully')
195
} catch (error) {
196
console.error('Save failed:', error)
197
}
198
}, 1000)
199
200
// Method debouncing with context
201
class AutoSave {
202
data: any = {}
203
204
updateData(key: string, value: any) {
205
this.data[key] = value
206
this.debouncedSave()
207
}
208
209
debouncedSave = debounce(function(this: AutoSave) {
210
console.log('Auto-saving data:', this.data)
211
// Save to storage
212
}, 2000, this)
213
}
214
```
215
216
## DOM Utilities
217
218
### Element Type Checking
219
220
```typescript { .api }
221
import { isElement, isText, isComment } from '@tarojs/runtime'
222
223
// Element type checks
224
function isElement(node: TaroNode): node is TaroElement
225
function isText(node: TaroNode): node is TaroText
226
function isComment(node: TaroNode): boolean
227
```
228
229
#### Usage Examples
230
231
```typescript
232
// Type-safe DOM manipulation
233
function processNode(node: TaroNode) {
234
if (isElement(node)) {
235
// TypeScript knows this is TaroElement
236
console.log('Element tag:', node.tagName)
237
console.log('Element attributes:', node.attributes)
238
node.setAttribute('processed', 'true')
239
} else if (isText(node)) {
240
// TypeScript knows this is TaroText
241
console.log('Text content:', node.textContent)
242
node.textContent = node.textContent.trim()
243
} else if (isComment(node)) {
244
console.log('Comment node found')
245
// Handle comment node
246
}
247
}
248
249
// Filter node collections
250
function getElements(nodes: TaroNode[]): TaroElement[] {
251
return nodes.filter(isElement)
252
}
253
254
function getTextNodes(nodes: TaroNode[]): TaroText[] {
255
return nodes.filter(isText)
256
}
257
258
// DOM traversal
259
function walkDOM(node: TaroNode, callback: (node: TaroNode) => void) {
260
callback(node)
261
262
if (isElement(node)) {
263
node.childNodes.forEach(child => walkDOM(child, callback))
264
}
265
}
266
```
267
268
### Property Utilities
269
270
```typescript { .api }
271
import {
272
isHasExtractProp,
273
isParentBinded,
274
shortcutAttr
275
} from '@tarojs/runtime'
276
277
// Property extraction check
278
function isHasExtractProp(element: TaroElement): boolean
279
280
// Event binding check
281
function isParentBinded(element: TaroElement, eventType: string): boolean
282
283
// Attribute shortcuts
284
function shortcutAttr(key: string): string
285
```
286
287
#### Usage Examples
288
289
```typescript
290
// Check if element has extractable properties
291
const element = document.createElement('custom-component')
292
element.setAttribute('custom-prop', 'value')
293
294
if (isHasExtractProp(element)) {
295
console.log('Element has non-standard properties')
296
// Handle custom property extraction
297
}
298
299
// Check event delegation
300
const child = document.createElement('button')
301
const parent = document.createElement('view')
302
parent.addEventListener('tap', handleTap)
303
parent.appendChild(child)
304
305
if (isParentBinded(child, 'tap')) {
306
console.log('Parent handles tap events')
307
// Skip adding duplicate listener
308
} else {
309
child.addEventListener('tap', handleTap)
310
}
311
312
// Attribute shortcuts
313
console.log(shortcutAttr('className')) // 'class'
314
console.log(shortcutAttr('htmlFor')) // 'for'
315
```
316
317
### ID Generation
318
319
```typescript { .api }
320
import { incrementId } from '@tarojs/runtime'
321
322
function incrementId(): () => string
323
```
324
325
#### Key Features
326
327
- **Unique IDs**: Generates unique identifiers using A-Z, a-z sequence
328
- **Deterministic**: Consistent ID generation across sessions
329
- **Performance**: Fast generation without collision checking
330
331
#### Usage Examples
332
333
```typescript
334
// Create ID generator
335
const getId = incrementId()
336
337
// Generate unique IDs
338
const id1 = getId() // 'A'
339
const id2 = getId() // 'B'
340
const id3 = getId() // 'C'
341
// ... continues through alphabet
342
343
// Use in component creation
344
function createUniqueElement(tagName: string): TaroElement {
345
const element = document.createElement(tagName)
346
element.id = getId()
347
return element
348
}
349
350
// Multiple generators for different purposes
351
const nodeIdGen = incrementId()
352
const componentIdGen = incrementId()
353
354
const nodeId = nodeIdGen() // Independent sequence
355
const componentId = componentIdGen() // Independent sequence
356
```
357
358
## Event Management
359
360
### Event Center
361
362
```typescript { .api }
363
import { eventCenter, Events } from '@tarojs/runtime'
364
365
interface EventsType {
366
// Event registration
367
on(eventName: string, listener: Function, context?: any): EventsType
368
once(eventName: string, listener: Function, context?: any): EventsType
369
370
// Event emission
371
trigger(eventName: string, ...args: any[]): EventsType
372
emit(eventName: string, ...args: any[]): EventsType
373
374
// Event removal
375
off(eventName?: string, listener?: Function, context?: any): EventsType
376
}
377
378
const eventCenter: EventsType
379
```
380
381
#### Key Features
382
383
- **Global Communication**: Cross-component and cross-page event communication
384
- **Context Binding**: Automatic `this` binding for event handlers
385
- **One-time Events**: Support for single-execution event handlers
386
- **Flexible Removal**: Remove specific listeners or all listeners for an event
387
388
#### Usage Examples
389
390
```typescript
391
// Basic event communication
392
eventCenter.on('user-login', (user: User) => {
393
console.log('User logged in:', user.name)
394
updateUserInterface(user)
395
})
396
397
eventCenter.trigger('user-login', { name: 'John', id: '123' })
398
399
// Cross-component communication
400
// Component A
401
class ComponentA extends React.Component {
402
sendMessage = () => {
403
eventCenter.trigger('message-sent', {
404
from: 'ComponentA',
405
message: 'Hello from A'
406
})
407
}
408
}
409
410
// Component B
411
class ComponentB extends React.Component {
412
componentDidMount() {
413
eventCenter.on('message-sent', this.handleMessage, this)
414
}
415
416
componentWillUnmount() {
417
eventCenter.off('message-sent', this.handleMessage, this)
418
}
419
420
handleMessage = (data: { from: string, message: string }) => {
421
console.log(`Message from ${data.from}: ${data.message}`)
422
}
423
}
424
425
// One-time events
426
eventCenter.once('app-initialized', () => {
427
console.log('App initialization complete')
428
// This handler will only run once
429
})
430
431
// Event cleanup
432
class EventfulComponent {
433
listeners = new Map()
434
435
componentDidMount() {
436
// Store listeners for cleanup
437
this.listeners.set('data-update', this.handleDataUpdate)
438
this.listeners.set('user-action', this.handleUserAction)
439
440
// Register events
441
eventCenter.on('data-update', this.handleDataUpdate, this)
442
eventCenter.on('user-action', this.handleUserAction, this)
443
}
444
445
componentWillUnmount() {
446
// Clean up all listeners
447
this.listeners.forEach((handler, eventName) => {
448
eventCenter.off(eventName, handler, this)
449
})
450
}
451
452
handleDataUpdate = (data: any) => { /* ... */ }
453
handleUserAction = (action: any) => { /* ... */ }
454
}
455
```
456
457
## Async Operations
458
459
### nextTick
460
461
```typescript { .api }
462
import { nextTick } from '@tarojs/runtime'
463
464
function nextTick(
465
callback: Function,
466
context?: Record<string, any>
467
): void
468
```
469
470
#### Key Features
471
472
- **Update Coordination**: Executes callback after next DOM update cycle
473
- **Context Binding**: Supports custom execution context
474
- **Timeout Fallback**: Uses `setTimeout` if update queue unavailable
475
476
#### Usage Examples
477
478
```typescript
479
// Wait for DOM updates
480
function updateComponent() {
481
// Modify DOM
482
element.textContent = 'Updated content'
483
element.className = 'new-class'
484
485
// Execute after DOM update
486
nextTick(() => {
487
console.log('DOM updates completed')
488
// Safe to read computed styles, dimensions, etc.
489
const rect = element.getBoundingClientRect()
490
console.log('Element dimensions:', rect)
491
})
492
}
493
494
// React integration
495
class ReactComponent extends React.Component {
496
updateData = () => {
497
this.setState({ data: newData }, () => {
498
// Execute after React update
499
nextTick(() => {
500
// Execute after Taro DOM update
501
console.log('Both React and Taro updates complete')
502
})
503
})
504
}
505
}
506
507
// Custom context
508
const context = { name: 'CustomContext' }
509
nextTick(function() {
510
console.log('Context:', this.name) // 'CustomContext'
511
}, context)
512
513
// Chained operations
514
function performComplexUpdate() {
515
// Step 1: Update data
516
updateApplicationData()
517
518
nextTick(() => {
519
// Step 2: Update DOM after data update
520
updateDOMElements()
521
522
nextTick(() => {
523
// Step 3: Final operations after DOM update
524
performFinalOperations()
525
})
526
})
527
}
528
```
529
530
### Hydration System
531
532
```typescript { .api }
533
import { hydrate } from '@tarojs/runtime'
534
535
function hydrate(node: TaroElement | TaroText): MiniData
536
537
interface MiniData {
538
[key: string]: any
539
// Converted mini-program data structure
540
}
541
```
542
543
#### Key Features
544
545
- **DOM to Data**: Converts DOM nodes to mini-program data structure
546
- **Component Aliasing**: Maps generic components to platform-specific ones
547
- **View Optimization**: Optimizes view types for performance
548
- **Property Filtering**: Filters out non-standard properties
549
550
#### Usage Examples
551
552
```typescript
553
// Hydrate DOM tree for mini-program
554
const element = document.createElement('view')
555
element.className = 'container'
556
element.textContent = 'Hello World'
557
element.style.color = 'red'
558
559
const miniData = hydrate(element)
560
console.log('Mini-program data:', miniData)
561
// Output: { cn: [{ v: 'Hello World' }], st: { color: 'red' }, ... }
562
563
// Hydrate complex component tree
564
const complexElement = document.createElement('scroll-view')
565
complexElement.setAttribute('scroll-y', 'true')
566
567
const listItem = document.createElement('view')
568
listItem.className = 'list-item'
569
listItem.textContent = 'Item 1'
570
complexElement.appendChild(listItem)
571
572
const hydratedData = hydrate(complexElement)
573
console.log('Complex hydration:', hydratedData)
574
575
// Use in custom rendering
576
function customRender(virtualDOM: TaroElement) {
577
const miniData = hydrate(virtualDOM)
578
579
// Send to mini-program
580
if (getCurrentInstance().page) {
581
getCurrentInstance().page.setData({
582
customComponent: miniData
583
})
584
}
585
}
586
```
587
588
## Router Utilities
589
590
### URL Utilities
591
592
```typescript { .api }
593
import {
594
addLeadingSlash,
595
hasBasename,
596
stripBasename,
597
stripTrailing,
598
stripSuffix
599
} from '@tarojs/runtime'
600
601
// URL formatting
602
function addLeadingSlash(path: string): string
603
function stripTrailing(path: string): string
604
function stripSuffix(path: string, suffix: string): string
605
606
// Basename handling
607
function hasBasename(path: string, basename: string): boolean
608
function stripBasename(path: string, basename: string): string
609
```
610
611
#### Usage Examples
612
613
```typescript
614
// URL formatting
615
console.log(addLeadingSlash('path/to/page')) // '/path/to/page'
616
console.log(addLeadingSlash('/path/to/page')) // '/path/to/page'
617
618
console.log(stripTrailing('/path/to/page/')) // '/path/to/page'
619
console.log(stripTrailing('/path/to/page')) // '/path/to/page'
620
621
console.log(stripSuffix('/page.html', '.html')) // '/page'
622
console.log(stripSuffix('/page', '.html')) // '/page'
623
624
// Basename handling
625
const basename = '/app'
626
const fullPath = '/app/pages/home'
627
628
console.log(hasBasename(fullPath, basename)) // true
629
console.log(stripBasename(fullPath, basename)) // '/pages/home'
630
631
// Route processing
632
function processRoute(rawPath: string, appBasename: string = ''): string {
633
let path = addLeadingSlash(rawPath)
634
path = stripTrailing(path)
635
636
if (appBasename && hasBasename(path, appBasename)) {
637
path = stripBasename(path, appBasename)
638
}
639
640
return path
641
}
642
643
console.log(processRoute('pages/home/', '/myapp')) // '/pages/home'
644
```
645
646
### Page Utilities
647
648
```typescript { .api }
649
import { getHomePage, getCurrentPage } from '@tarojs/runtime'
650
651
// Get application home page
652
function getHomePage(): string
653
654
// Get current page path
655
function getCurrentPage(): string
656
```
657
658
#### Usage Examples
659
660
```typescript
661
// Navigation helpers
662
function navigateHome() {
663
const homePage = getHomePage()
664
wx.navigateTo({ url: homePage })
665
}
666
667
function refreshCurrentPage() {
668
const currentPage = getCurrentPage()
669
wx.redirectTo({ url: currentPage })
670
}
671
672
// Breadcrumb generation
673
function generateBreadcrumb(): string[] {
674
const current = getCurrentPage()
675
const home = getHomePage()
676
677
const breadcrumb = [home]
678
if (current !== home) {
679
breadcrumb.push(current)
680
}
681
682
return breadcrumb
683
}
684
```
685
686
## Cache Management
687
688
### RuntimeCache
689
690
```typescript { .api }
691
import { RuntimeCache } from '@tarojs/runtime'
692
693
class RuntimeCache<T = any> {
694
// Cache operations
695
set(key: string, value: T): void
696
get(key: string): T | undefined
697
has(key: string): boolean
698
delete(key: string): boolean
699
clear(): void
700
701
// Iteration
702
keys(): IterableIterator<string>
703
values(): IterableIterator<T>
704
entries(): IterableIterator<[string, T]>
705
706
// Properties
707
readonly size: number
708
}
709
```
710
711
#### Key Features
712
713
- **Context-aware**: Automatic cleanup based on page context
714
- **Type-safe**: Generic type support for cached values
715
- **Memory Management**: Automatic cleanup to prevent memory leaks
716
717
#### Usage Examples
718
719
```typescript
720
// Create cache instance
721
const pageCache = new RuntimeCache<PageData>()
722
const componentCache = new RuntimeCache<ComponentState>()
723
724
// Cache page data
725
interface PageData {
726
userInfo: User
727
settings: AppSettings
728
}
729
730
pageCache.set('user-profile', {
731
userInfo: { id: '123', name: 'John' },
732
settings: { theme: 'dark', lang: 'en' }
733
})
734
735
// Retrieve cached data
736
const cachedData = pageCache.get('user-profile')
737
if (cachedData) {
738
console.log('Cached user:', cachedData.userInfo.name)
739
}
740
741
// Cache management
742
console.log('Cache size:', pageCache.size)
743
console.log('Has user data:', pageCache.has('user-profile'))
744
745
// Iterate cache
746
for (const [key, value] of pageCache.entries()) {
747
console.log(`Cached ${key}:`, value)
748
}
749
750
// Cleanup
751
pageCache.delete('old-data')
752
pageCache.clear() // Clear all cache
753
754
// Component state caching
755
class CacheableComponent extends React.Component {
756
cache = new RuntimeCache<ComponentState>()
757
758
componentDidMount() {
759
const cached = this.cache.get('component-state')
760
if (cached) {
761
this.setState(cached)
762
}
763
}
764
765
componentWillUnmount() {
766
this.cache.set('component-state', this.state)
767
}
768
}
769
```
770
771
## Runtime Configuration
772
773
### Options
774
775
```typescript { .api }
776
import { options } from '@tarojs/runtime'
777
778
interface Options {
779
prerender: boolean // Enable prerendering (default: true)
780
debug: boolean // Enable debug mode (default: false)
781
}
782
783
const options: Options
784
```
785
786
#### Usage Examples
787
788
```typescript
789
// Configure runtime behavior
790
options.prerender = false // Disable prerendering
791
options.debug = true // Enable debug logging
792
793
// Conditional behavior
794
if (options.debug) {
795
console.log('Debug mode enabled')
796
// Additional logging
797
}
798
799
if (options.prerender) {
800
// Prerender optimization enabled
801
performPrerenderOptimizations()
802
}
803
804
// Environment-based configuration
805
if (process.env.NODE_ENV === 'development') {
806
options.debug = true
807
}
808
809
if (process.env.NODE_ENV === 'production') {
810
options.prerender = true
811
options.debug = false
812
}
813
```
814
815
## Polyfills
816
817
### handlePolyfill
818
819
```typescript { .api }
820
import { handlePolyfill } from '@tarojs/runtime'
821
822
function handlePolyfill(): void
823
```
824
825
#### Key Features
826
827
- **Conditional Polyfills**: Only applies needed polyfills based on environment
828
- **Standard APIs**: Polyfills for `Object.assign`, `Array.find`, etc.
829
- **Web-specific**: `IntersectionObserver` polyfill for web platforms
830
831
#### Usage Examples
832
833
```typescript
834
// Apply polyfills (usually done automatically)
835
handlePolyfill()
836
837
// Manual polyfill check
838
if (typeof Object.assign !== 'function') {
839
handlePolyfill() // Will apply Object.assign polyfill
840
}
841
842
// Environment-specific polyfills
843
if (typeof window !== 'undefined') {
844
// Web environment - full polyfills applied
845
handlePolyfill()
846
}
847
```
848
849
## Helper Functions
850
851
### General Utilities
852
853
```typescript { .api }
854
import { extend, getComponentsAlias, convertNumber2PX } from '@tarojs/runtime'
855
856
// Object extension
857
function extend(target: any, ...sources: any[]): any
858
859
// Component mapping
860
function getComponentsAlias(): Record<string, string>
861
862
// Unit conversion
863
function convertNumber2PX(value: number | string): string
864
```
865
866
#### Usage Examples
867
868
```typescript
869
// Object extension (like Object.assign)
870
const base = { a: 1, b: 2 }
871
const extended = extend(base, { b: 3, c: 4 }, { d: 5 })
872
console.log(extended) // { a: 1, b: 3, c: 4, d: 5 }
873
874
// Component aliasing
875
const aliases = getComponentsAlias()
876
console.log(aliases) // { 'scroll-view': 'ScrollView', ... }
877
878
// Convert to px units
879
console.log(convertNumber2PX(16)) // '16px'
880
console.log(convertNumber2PX('16')) // '16px'
881
console.log(convertNumber2PX('16px')) // '16px'
882
883
// Use in style processing
884
function normalizeStyleValue(value: any): string {
885
if (typeof value === 'number') {
886
return convertNumber2PX(value)
887
}
888
return String(value)
889
}
890
```
891
892
## Environment & Runtime APIs
893
894
### Environment Detection
895
896
```typescript { .api }
897
import { env } from '@tarojs/runtime'
898
899
interface Env {
900
window: Window | {}
901
document: Document | {}
902
}
903
904
const env: Env
905
```
906
907
#### Usage Examples
908
909
```typescript
910
// Check platform capabilities
911
if (env.window && 'addEventListener' in env.window) {
912
// Web platform - use native APIs
913
env.window.addEventListener('resize', handleResize)
914
} else {
915
// Mini-program platform - use alternatives
916
// Handle resize through Taro lifecycle
917
}
918
919
// Safe document access
920
if (env.document && 'createElement' in env.document) {
921
// Native DOM available
922
const element = env.document.createElement('div')
923
} else {
924
// Use Taro DOM polyfills
925
const element = document.createElement('view')
926
}
927
```
928
929
### URL Parsing
930
931
```typescript { .api }
932
import { parseUrl } from '@tarojs/runtime'
933
934
function parseUrl(url?: string): {
935
href: string
936
origin: string
937
protocol: string
938
hostname: string
939
host: string
940
port: string
941
pathname: string
942
search: string
943
hash: string
944
}
945
```
946
947
#### Usage Examples
948
949
```typescript
950
// Parse complete URLs
951
const parsed = parseUrl('https://example.com:8080/path?query=value#section')
952
console.log(parsed.hostname) // 'example.com'
953
console.log(parsed.port) // '8080'
954
console.log(parsed.pathname) // '/path'
955
console.log(parsed.search) // '?query=value'
956
console.log(parsed.hash) // '#section'
957
958
// Handle partial URLs
959
const relative = parseUrl('/api/users?page=1')
960
console.log(relative.pathname) // '/api/users'
961
console.log(relative.search) // '?page=1'
962
963
// Safe URL parsing
964
function getUrlParts(url: string) {
965
try {
966
const parts = parseUrl(url)
967
return parts.pathname + parts.search
968
} catch (error) {
969
return '/'
970
}
971
}
972
```
973
974
### Hooks System
975
976
```typescript { .api }
977
import { hooks } from '@tarojs/runtime'
978
979
interface Hooks {
980
call<T>(hookName: string, ...args: any[]): T
981
tap(hookName: string, callback: Function): void
982
}
983
984
const hooks: Hooks
985
```
986
987
#### Usage Examples
988
989
```typescript
990
// Register hook handlers
991
hooks.tap('beforeMount', (component) => {
992
console.log('Component mounting:', component)
993
})
994
995
hooks.tap('afterUpdate', (instance) => {
996
console.log('Component updated:', instance)
997
})
998
999
// Call hooks programmatically
1000
const eventCenter = hooks.call('getEventCenter', Events)
1001
const router = hooks.call('getRouter')
1002
1003
// Custom hook integration
1004
hooks.tap('customEvent', (data) => {
1005
// Handle custom events
1006
processCustomData(data)
1007
})
1008
1009
// Trigger custom hooks
1010
hooks.call('customEvent', { type: 'user-action', payload: data })
1011
```
1012
1013
The utilities module provides essential tools for building performant, maintainable cross-platform applications with comprehensive performance monitoring, event management, and optimization capabilities.