0
# Route Navigation APIs
1
2
Page navigation and routing capabilities integrated with @tarojs/router for single-page application navigation, providing programmatic control over page transitions and history management.
3
4
## Capabilities
5
6
### Page Navigation
7
8
Navigate between pages in the application with various navigation modes and parameter passing.
9
10
```typescript { .api }
11
/**
12
* Navigate to a new page, keeping current page in history stack
13
* @param options - Navigation configuration
14
* @returns Promise that resolves when navigation completes
15
*/
16
function navigateTo(options: NavigateOption): Promise<void>;
17
18
/**
19
* Replace current page with a new page (no history stack change)
20
* @param options - Redirect configuration
21
* @returns Promise that resolves when redirect completes
22
*/
23
function redirectTo(options: RedirectOption): Promise<void>;
24
25
/**
26
* Navigate back in the page history stack
27
* @param options - Navigation back configuration
28
* @returns Promise that resolves when navigation completes
29
*/
30
function navigateBack(options?: NavigateBackOption): Promise<void>;
31
32
/**
33
* Switch to a tab page (for tab-based applications)
34
* @param options - Tab switch configuration
35
* @returns Promise that resolves when tab switch completes
36
*/
37
function switchTab(options: SwitchTabOption): Promise<void>;
38
39
/**
40
* Restart the application with a new page as the root
41
* @param options - Relaunch configuration
42
* @returns Promise that resolves when relaunch completes
43
*/
44
function reLaunch(options: ReLaunchOption): Promise<void>;
45
46
interface NavigateOption extends CallbackOptions {
47
/** Target page URL path (required) */
48
url: string;
49
/** Event handlers for cross-page communication */
50
events?: Record<string, Function>;
51
/** Animation type for transition */
52
animationType?: 'slide-in-right' | 'slide-in-left' | 'slide-in-top' | 'slide-in-bottom' | 'fade-in' | 'zoom-in' | 'zoom-fade-in' | 'none';
53
/** Animation duration in milliseconds */
54
animationDuration?: number;
55
}
56
57
interface RedirectOption extends CallbackOptions {
58
/** Target page URL path (required) */
59
url: string;
60
}
61
62
interface NavigateBackOption extends CallbackOptions {
63
/** Number of pages to go back (default: 1) */
64
delta?: number;
65
/** Animation type for back transition */
66
animationType?: 'slide-out-right' | 'slide-out-left' | 'slide-out-top' | 'slide-out-bottom' | 'fade-out' | 'zoom-out' | 'zoom-fade-out' | 'none';
67
/** Animation duration in milliseconds */
68
animationDuration?: number;
69
}
70
71
interface SwitchTabOption extends CallbackOptions {
72
/** Tab page URL path (required) */
73
url: string;
74
}
75
76
interface ReLaunchOption extends CallbackOptions {
77
/** New root page URL path (required) */
78
url: string;
79
}
80
```
81
82
**Usage Examples:**
83
84
```typescript
85
import { navigateTo, redirectTo, navigateBack, switchTab, reLaunch } from "@tarojs/taro-h5";
86
87
// Basic navigation to a new page
88
await navigateTo({
89
url: '/pages/profile/index'
90
});
91
92
// Navigation with query parameters
93
await navigateTo({
94
url: '/pages/product/detail?id=123&category=electronics'
95
});
96
97
// Navigation with custom animation
98
await navigateTo({
99
url: '/pages/settings/index',
100
animationType: 'slide-in-left',
101
animationDuration: 300
102
});
103
104
// Navigate with event handlers for communication
105
await navigateTo({
106
url: '/pages/editor/index',
107
events: {
108
// Listen for events from the target page
109
acceptDataFromOpenedPage: (data) => {
110
console.log('Received data from editor:', data);
111
},
112
someEvent: (eventData) => {
113
console.log('Custom event received:', eventData);
114
}
115
}
116
});
117
118
// Redirect (replace current page)
119
await redirectTo({
120
url: '/pages/login/index'
121
});
122
123
// Navigate back one page
124
await navigateBack();
125
126
// Navigate back multiple pages
127
await navigateBack({
128
delta: 3 // Go back 3 pages
129
});
130
131
// Navigate back with animation
132
await navigateBack({
133
delta: 1,
134
animationType: 'slide-out-right',
135
animationDuration: 250
136
});
137
138
// Switch to tab page
139
await switchTab({
140
url: '/pages/home/index'
141
});
142
143
// Restart app with new root page
144
await reLaunch({
145
url: '/pages/welcome/index'
146
});
147
```
148
149
### Router Information
150
151
Access current routing information and page context.
152
153
```typescript { .api }
154
/**
155
* Router object providing navigation utilities
156
* Note: Limited functionality in H5 environment
157
*/
158
interface Router {
159
/** Add route builder (not supported in H5) */
160
addRouteBuilder(): never;
161
/** Get route context (not supported in H5) */
162
getRouteContext(): never;
163
/** Remove route builder (not supported in H5) */
164
removeRouteBuilder(): never;
165
}
166
167
/**
168
* Current router information from @tarojs/router
169
*/
170
interface RouterInfo {
171
/** Current page path */
172
path: string;
173
/** Query parameters object */
174
params: Record<string, string>;
175
/** Route configuration */
176
$taroPath?: string;
177
/** Route index in stack */
178
$taroTimestamp?: number;
179
}
180
```
181
182
### Advanced Navigation Patterns
183
184
Complex navigation scenarios and best practices for application flow management.
185
186
```typescript
187
// Navigation service for complex routing logic
188
class NavigationService {
189
private static instance: NavigationService;
190
private navigationHistory: string[] = [];
191
private maxHistorySize = 50;
192
193
static getInstance(): NavigationService {
194
if (!NavigationService.instance) {
195
NavigationService.instance = new NavigationService();
196
}
197
return NavigationService.instance;
198
}
199
200
async goToPage(url: string, options?: Partial<NavigateOption>): Promise<void> {
201
try {
202
await navigateTo({
203
url,
204
...options
205
});
206
207
// Track navigation history
208
this.navigationHistory.push(url);
209
if (this.navigationHistory.length > this.maxHistorySize) {
210
this.navigationHistory.shift();
211
}
212
213
console.log('Navigated to:', url);
214
} catch (error) {
215
console.error('Navigation failed:', error);
216
throw error;
217
}
218
}
219
220
async replacePage(url: string, options?: Partial<RedirectOption>): Promise<void> {
221
try {
222
await redirectTo({
223
url,
224
...options
225
});
226
227
// Update last entry in history instead of adding
228
if (this.navigationHistory.length > 0) {
229
this.navigationHistory[this.navigationHistory.length - 1] = url;
230
} else {
231
this.navigationHistory.push(url);
232
}
233
234
console.log('Redirected to:', url);
235
} catch (error) {
236
console.error('Redirect failed:', error);
237
throw error;
238
}
239
}
240
241
async goBack(pages: number = 1): Promise<void> {
242
try {
243
await navigateBack({ delta: pages });
244
245
// Update navigation history
246
for (let i = 0; i < pages && this.navigationHistory.length > 0; i++) {
247
this.navigationHistory.pop();
248
}
249
250
console.log(`Navigated back ${pages} page(s)`);
251
} catch (error) {
252
console.error('Navigate back failed:', error);
253
throw error;
254
}
255
}
256
257
async restartApp(rootUrl: string): Promise<void> {
258
try {
259
await reLaunch({ url: rootUrl });
260
261
// Clear navigation history
262
this.navigationHistory = [rootUrl];
263
264
console.log('App restarted with root:', rootUrl);
265
} catch (error) {
266
console.error('App restart failed:', error);
267
throw error;
268
}
269
}
270
271
getNavigationHistory(): string[] {
272
return [...this.navigationHistory];
273
}
274
275
getPreviousPage(): string | null {
276
return this.navigationHistory.length > 1
277
? this.navigationHistory[this.navigationHistory.length - 2]
278
: null;
279
}
280
281
getCurrentPage(): string | null {
282
return this.navigationHistory.length > 0
283
? this.navigationHistory[this.navigationHistory.length - 1]
284
: null;
285
}
286
}
287
288
// Route parameter handling
289
class RouteParams {
290
static parse(url: string): { path: string; params: Record<string, string> } {
291
const [path, queryString] = url.split('?');
292
const params: Record<string, string> = {};
293
294
if (queryString) {
295
queryString.split('&').forEach(param => {
296
const [key, value] = param.split('=');
297
if (key && value) {
298
params[decodeURIComponent(key)] = decodeURIComponent(value);
299
}
300
});
301
}
302
303
return { path, params };
304
}
305
306
static stringify(path: string, params: Record<string, any>): string {
307
const queryParams = Object.entries(params)
308
.filter(([_, value]) => value != null)
309
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
310
.join('&');
311
312
return queryParams ? `${path}?${queryParams}` : path;
313
}
314
315
static getCurrentParams(): Record<string, string> {
316
const instance = getCurrentInstance();
317
return instance?.router?.params || {};
318
}
319
}
320
321
// Tab navigation manager
322
class TabNavigationManager {
323
private activeTabIndex = 0;
324
private tabs: TabConfig[] = [];
325
326
constructor(tabs: TabConfig[]) {
327
this.tabs = tabs;
328
}
329
330
async switchToTab(index: number): Promise<void> {
331
if (index < 0 || index >= this.tabs.length) {
332
throw new Error('Invalid tab index');
333
}
334
335
const tab = this.tabs[index];
336
await switchTab({ url: tab.pagePath });
337
338
this.activeTabIndex = index;
339
console.log('Switched to tab:', tab.text);
340
}
341
342
async switchToTabByPath(path: string): Promise<void> {
343
const tabIndex = this.tabs.findIndex(tab => tab.pagePath === path);
344
if (tabIndex === -1) {
345
throw new Error('Tab not found for path: ' + path);
346
}
347
348
await this.switchToTab(tabIndex);
349
}
350
351
getCurrentTab(): TabConfig | null {
352
return this.tabs[this.activeTabIndex] || null;
353
}
354
355
getTabByIndex(index: number): TabConfig | null {
356
return this.tabs[index] || null;
357
}
358
359
getAllTabs(): TabConfig[] {
360
return [...this.tabs];
361
}
362
}
363
364
interface TabConfig {
365
pagePath: string;
366
text: string;
367
iconPath?: string;
368
selectedIconPath?: string;
369
}
370
371
// Authentication-aware navigation
372
class AuthNavigationGuard {
373
private static redirectAfterLogin: string | null = null;
374
375
static async navigateWithAuth(url: string, options?: Partial<NavigateOption>): Promise<void> {
376
const isAuthenticated = await this.checkAuthentication();
377
378
if (!isAuthenticated) {
379
// Store intended destination
380
this.redirectAfterLogin = url;
381
382
// Redirect to login
383
await redirectTo({ url: '/pages/login/index' });
384
return;
385
}
386
387
// User is authenticated, proceed with navigation
388
await navigateTo({ url, ...options });
389
}
390
391
static async handleLoginSuccess(): Promise<void> {
392
if (this.redirectAfterLogin) {
393
const destination = this.redirectAfterLogin;
394
this.redirectAfterLogin = null;
395
396
await redirectTo({ url: destination });
397
} else {
398
await switchTab({ url: '/pages/home/index' });
399
}
400
}
401
402
static async logout(): Promise<void> {
403
// Clear authentication
404
removeStorageSync('authToken');
405
removeStorageSync('userInfo');
406
407
// Clear redirect destination
408
this.redirectAfterLogin = null;
409
410
// Restart app with login page
411
await reLaunch({ url: '/pages/login/index' });
412
}
413
414
private static async checkAuthentication(): Promise<boolean> {
415
const token = getStorageSync('authToken');
416
if (!token) return false;
417
418
try {
419
// Verify token with server
420
const response = await request({
421
url: '/api/auth/verify',
422
method: 'POST',
423
header: { Authorization: `Bearer ${token}` }
424
});
425
426
return response.statusCode === 200;
427
} catch {
428
return false;
429
}
430
}
431
}
432
433
// Usage examples
434
const nav = NavigationService.getInstance();
435
const params = RouteParams;
436
const authGuard = AuthNavigationGuard;
437
438
// Complex navigation with parameters
439
async function navigateToProductDetail(productId: string, category: string) {
440
const url = params.stringify('/pages/product/detail', {
441
id: productId,
442
category,
443
timestamp: Date.now()
444
});
445
446
await nav.goToPage(url, {
447
animationType: 'slide-in-right'
448
});
449
}
450
451
// Navigate with authentication check
452
async function navigateToSecurePage() {
453
await authGuard.navigateWithAuth('/pages/account/settings', {
454
animationType: 'fade-in'
455
});
456
}
457
458
// Tab navigation setup
459
const tabManager = new TabNavigationManager([
460
{ pagePath: '/pages/home/index', text: 'Home' },
461
{ pagePath: '/pages/discover/index', text: 'Discover' },
462
{ pagePath: '/pages/profile/index', text: 'Profile' }
463
]);
464
465
await tabManager.switchToTab(1); // Switch to Discover tab
466
```
467
468
### Page Communication
469
470
Cross-page communication patterns for data sharing and event handling.
471
472
```typescript
473
// Event-based page communication
474
class PageCommunication {
475
private static eventBus = new Map<string, Function[]>();
476
477
static emit(event: string, data: any): void {
478
const listeners = this.eventBus.get(event) || [];
479
listeners.forEach(callback => {
480
try {
481
callback(data);
482
} catch (error) {
483
console.error('Page communication error:', error);
484
}
485
});
486
}
487
488
static on(event: string, callback: Function): void {
489
const listeners = this.eventBus.get(event) || [];
490
listeners.push(callback);
491
this.eventBus.set(event, listeners);
492
}
493
494
static off(event: string, callback?: Function): void {
495
if (!callback) {
496
this.eventBus.delete(event);
497
return;
498
}
499
500
const listeners = this.eventBus.get(event) || [];
501
const filtered = listeners.filter(cb => cb !== callback);
502
this.eventBus.set(event, filtered);
503
}
504
505
static once(event: string, callback: Function): void {
506
const onceCallback = (data: any) => {
507
callback(data);
508
this.off(event, onceCallback);
509
};
510
this.on(event, onceCallback);
511
}
512
}
513
514
// Usage in page components
515
function navigateWithCallback() {
516
// Listen for data from target page
517
PageCommunication.once('editor:save', (savedData) => {
518
console.log('Editor saved data:', savedData);
519
updateLocalData(savedData);
520
});
521
522
// Navigate to editor
523
navigateTo({
524
url: '/pages/editor/index?mode=create',
525
events: {
526
// Alternative event handling via navigateTo options
527
editorComplete: (data) => {
528
console.log('Editor completed:', data);
529
}
530
}
531
});
532
}
533
534
// In editor page
535
function saveAndReturn(data: any) {
536
// Emit event to parent page
537
PageCommunication.emit('editor:save', data);
538
539
// Navigate back
540
navigateBack();
541
}
542
```
543
544
## Error Handling
545
546
Navigation operations can fail due to invalid URLs, missing pages, or system restrictions.
547
548
```typescript
549
// Comprehensive navigation error handling
550
async function safeNavigate(url: string, options?: Partial<NavigateOption>): Promise<boolean> {
551
try {
552
await navigateTo({ url, ...options });
553
return true;
554
} catch (error: any) {
555
console.error('Navigation error:', error);
556
557
// Handle specific error types
558
if (error.message?.includes('page not found')) {
559
await showModal({
560
title: 'Page Not Found',
561
content: 'The requested page does not exist.',
562
showCancel: false
563
});
564
} else if (error.message?.includes('too many pages')) {
565
await showModal({
566
title: 'Too Many Pages',
567
content: 'Too many pages open. Please close some pages and try again.',
568
showCancel: false
569
});
570
} else {
571
await showToast({
572
title: 'Navigation failed',
573
icon: 'error'
574
});
575
}
576
577
return false;
578
}
579
}
580
581
// Safe back navigation with fallback
582
async function safeNavigateBack(delta: number = 1, fallbackUrl?: string): Promise<void> {
583
try {
584
const pages = getCurrentPages();
585
586
if (pages.length <= delta) {
587
// Not enough pages to go back, use fallback or redirect to home
588
const target = fallbackUrl || '/pages/home/index';
589
await redirectTo({ url: target });
590
} else {
591
await navigateBack({ delta });
592
}
593
} catch (error) {
594
console.error('Navigate back failed:', error);
595
596
// Fallback to home page
597
await reLaunch({ url: '/pages/home/index' });
598
}
599
}
600
```
601
602
## Types
603
604
```typescript { .api }
605
interface CallbackOptions {
606
success?: (res: any) => void;
607
fail?: (err: any) => void;
608
complete?: (res: any) => void;
609
}
610
611
type AnimationType =
612
| 'slide-in-right' | 'slide-in-left' | 'slide-in-top' | 'slide-in-bottom'
613
| 'slide-out-right' | 'slide-out-left' | 'slide-out-top' | 'slide-out-bottom'
614
| 'fade-in' | 'fade-out'
615
| 'zoom-in' | 'zoom-out'
616
| 'zoom-fade-in' | 'zoom-fade-out'
617
| 'none';
618
619
interface NavigationError extends Error {
620
code?: string;
621
type?: 'page_not_found' | 'too_many_pages' | 'invalid_url' | 'permission_denied';
622
}
623
```