H5端API库,为Taro跨端开发框架提供Web/H5端的API实现
—
Page navigation and routing capabilities integrated with @tarojs/router for single-page application navigation, providing programmatic control over page transitions and history management.
Navigate between pages in the application with various navigation modes and parameter passing.
/**
* Navigate to a new page, keeping current page in history stack
* @param options - Navigation configuration
* @returns Promise that resolves when navigation completes
*/
function navigateTo(options: NavigateOption): Promise<void>;
/**
* Replace current page with a new page (no history stack change)
* @param options - Redirect configuration
* @returns Promise that resolves when redirect completes
*/
function redirectTo(options: RedirectOption): Promise<void>;
/**
* Navigate back in the page history stack
* @param options - Navigation back configuration
* @returns Promise that resolves when navigation completes
*/
function navigateBack(options?: NavigateBackOption): Promise<void>;
/**
* Switch to a tab page (for tab-based applications)
* @param options - Tab switch configuration
* @returns Promise that resolves when tab switch completes
*/
function switchTab(options: SwitchTabOption): Promise<void>;
/**
* Restart the application with a new page as the root
* @param options - Relaunch configuration
* @returns Promise that resolves when relaunch completes
*/
function reLaunch(options: ReLaunchOption): Promise<void>;
interface NavigateOption extends CallbackOptions {
/** Target page URL path (required) */
url: string;
/** Event handlers for cross-page communication */
events?: Record<string, Function>;
/** Animation type for transition */
animationType?: 'slide-in-right' | 'slide-in-left' | 'slide-in-top' | 'slide-in-bottom' | 'fade-in' | 'zoom-in' | 'zoom-fade-in' | 'none';
/** Animation duration in milliseconds */
animationDuration?: number;
}
interface RedirectOption extends CallbackOptions {
/** Target page URL path (required) */
url: string;
}
interface NavigateBackOption extends CallbackOptions {
/** Number of pages to go back (default: 1) */
delta?: number;
/** Animation type for back transition */
animationType?: 'slide-out-right' | 'slide-out-left' | 'slide-out-top' | 'slide-out-bottom' | 'fade-out' | 'zoom-out' | 'zoom-fade-out' | 'none';
/** Animation duration in milliseconds */
animationDuration?: number;
}
interface SwitchTabOption extends CallbackOptions {
/** Tab page URL path (required) */
url: string;
}
interface ReLaunchOption extends CallbackOptions {
/** New root page URL path (required) */
url: string;
}Usage Examples:
import { navigateTo, redirectTo, navigateBack, switchTab, reLaunch } from "@tarojs/taro-h5";
// Basic navigation to a new page
await navigateTo({
url: '/pages/profile/index'
});
// Navigation with query parameters
await navigateTo({
url: '/pages/product/detail?id=123&category=electronics'
});
// Navigation with custom animation
await navigateTo({
url: '/pages/settings/index',
animationType: 'slide-in-left',
animationDuration: 300
});
// Navigate with event handlers for communication
await navigateTo({
url: '/pages/editor/index',
events: {
// Listen for events from the target page
acceptDataFromOpenedPage: (data) => {
console.log('Received data from editor:', data);
},
someEvent: (eventData) => {
console.log('Custom event received:', eventData);
}
}
});
// Redirect (replace current page)
await redirectTo({
url: '/pages/login/index'
});
// Navigate back one page
await navigateBack();
// Navigate back multiple pages
await navigateBack({
delta: 3 // Go back 3 pages
});
// Navigate back with animation
await navigateBack({
delta: 1,
animationType: 'slide-out-right',
animationDuration: 250
});
// Switch to tab page
await switchTab({
url: '/pages/home/index'
});
// Restart app with new root page
await reLaunch({
url: '/pages/welcome/index'
});Access current routing information and page context.
/**
* Router object providing navigation utilities
* Note: Limited functionality in H5 environment
*/
interface Router {
/** Add route builder (not supported in H5) */
addRouteBuilder(): never;
/** Get route context (not supported in H5) */
getRouteContext(): never;
/** Remove route builder (not supported in H5) */
removeRouteBuilder(): never;
}
/**
* Current router information from @tarojs/router
*/
interface RouterInfo {
/** Current page path */
path: string;
/** Query parameters object */
params: Record<string, string>;
/** Route configuration */
$taroPath?: string;
/** Route index in stack */
$taroTimestamp?: number;
}Complex navigation scenarios and best practices for application flow management.
// Navigation service for complex routing logic
class NavigationService {
private static instance: NavigationService;
private navigationHistory: string[] = [];
private maxHistorySize = 50;
static getInstance(): NavigationService {
if (!NavigationService.instance) {
NavigationService.instance = new NavigationService();
}
return NavigationService.instance;
}
async goToPage(url: string, options?: Partial<NavigateOption>): Promise<void> {
try {
await navigateTo({
url,
...options
});
// Track navigation history
this.navigationHistory.push(url);
if (this.navigationHistory.length > this.maxHistorySize) {
this.navigationHistory.shift();
}
console.log('Navigated to:', url);
} catch (error) {
console.error('Navigation failed:', error);
throw error;
}
}
async replacePage(url: string, options?: Partial<RedirectOption>): Promise<void> {
try {
await redirectTo({
url,
...options
});
// Update last entry in history instead of adding
if (this.navigationHistory.length > 0) {
this.navigationHistory[this.navigationHistory.length - 1] = url;
} else {
this.navigationHistory.push(url);
}
console.log('Redirected to:', url);
} catch (error) {
console.error('Redirect failed:', error);
throw error;
}
}
async goBack(pages: number = 1): Promise<void> {
try {
await navigateBack({ delta: pages });
// Update navigation history
for (let i = 0; i < pages && this.navigationHistory.length > 0; i++) {
this.navigationHistory.pop();
}
console.log(`Navigated back ${pages} page(s)`);
} catch (error) {
console.error('Navigate back failed:', error);
throw error;
}
}
async restartApp(rootUrl: string): Promise<void> {
try {
await reLaunch({ url: rootUrl });
// Clear navigation history
this.navigationHistory = [rootUrl];
console.log('App restarted with root:', rootUrl);
} catch (error) {
console.error('App restart failed:', error);
throw error;
}
}
getNavigationHistory(): string[] {
return [...this.navigationHistory];
}
getPreviousPage(): string | null {
return this.navigationHistory.length > 1
? this.navigationHistory[this.navigationHistory.length - 2]
: null;
}
getCurrentPage(): string | null {
return this.navigationHistory.length > 0
? this.navigationHistory[this.navigationHistory.length - 1]
: null;
}
}
// Route parameter handling
class RouteParams {
static parse(url: string): { path: string; params: Record<string, string> } {
const [path, queryString] = url.split('?');
const params: Record<string, string> = {};
if (queryString) {
queryString.split('&').forEach(param => {
const [key, value] = param.split('=');
if (key && value) {
params[decodeURIComponent(key)] = decodeURIComponent(value);
}
});
}
return { path, params };
}
static stringify(path: string, params: Record<string, any>): string {
const queryParams = Object.entries(params)
.filter(([_, value]) => value != null)
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
.join('&');
return queryParams ? `${path}?${queryParams}` : path;
}
static getCurrentParams(): Record<string, string> {
const instance = getCurrentInstance();
return instance?.router?.params || {};
}
}
// Tab navigation manager
class TabNavigationManager {
private activeTabIndex = 0;
private tabs: TabConfig[] = [];
constructor(tabs: TabConfig[]) {
this.tabs = tabs;
}
async switchToTab(index: number): Promise<void> {
if (index < 0 || index >= this.tabs.length) {
throw new Error('Invalid tab index');
}
const tab = this.tabs[index];
await switchTab({ url: tab.pagePath });
this.activeTabIndex = index;
console.log('Switched to tab:', tab.text);
}
async switchToTabByPath(path: string): Promise<void> {
const tabIndex = this.tabs.findIndex(tab => tab.pagePath === path);
if (tabIndex === -1) {
throw new Error('Tab not found for path: ' + path);
}
await this.switchToTab(tabIndex);
}
getCurrentTab(): TabConfig | null {
return this.tabs[this.activeTabIndex] || null;
}
getTabByIndex(index: number): TabConfig | null {
return this.tabs[index] || null;
}
getAllTabs(): TabConfig[] {
return [...this.tabs];
}
}
interface TabConfig {
pagePath: string;
text: string;
iconPath?: string;
selectedIconPath?: string;
}
// Authentication-aware navigation
class AuthNavigationGuard {
private static redirectAfterLogin: string | null = null;
static async navigateWithAuth(url: string, options?: Partial<NavigateOption>): Promise<void> {
const isAuthenticated = await this.checkAuthentication();
if (!isAuthenticated) {
// Store intended destination
this.redirectAfterLogin = url;
// Redirect to login
await redirectTo({ url: '/pages/login/index' });
return;
}
// User is authenticated, proceed with navigation
await navigateTo({ url, ...options });
}
static async handleLoginSuccess(): Promise<void> {
if (this.redirectAfterLogin) {
const destination = this.redirectAfterLogin;
this.redirectAfterLogin = null;
await redirectTo({ url: destination });
} else {
await switchTab({ url: '/pages/home/index' });
}
}
static async logout(): Promise<void> {
// Clear authentication
removeStorageSync('authToken');
removeStorageSync('userInfo');
// Clear redirect destination
this.redirectAfterLogin = null;
// Restart app with login page
await reLaunch({ url: '/pages/login/index' });
}
private static async checkAuthentication(): Promise<boolean> {
const token = getStorageSync('authToken');
if (!token) return false;
try {
// Verify token with server
const response = await request({
url: '/api/auth/verify',
method: 'POST',
header: { Authorization: `Bearer ${token}` }
});
return response.statusCode === 200;
} catch {
return false;
}
}
}
// Usage examples
const nav = NavigationService.getInstance();
const params = RouteParams;
const authGuard = AuthNavigationGuard;
// Complex navigation with parameters
async function navigateToProductDetail(productId: string, category: string) {
const url = params.stringify('/pages/product/detail', {
id: productId,
category,
timestamp: Date.now()
});
await nav.goToPage(url, {
animationType: 'slide-in-right'
});
}
// Navigate with authentication check
async function navigateToSecurePage() {
await authGuard.navigateWithAuth('/pages/account/settings', {
animationType: 'fade-in'
});
}
// Tab navigation setup
const tabManager = new TabNavigationManager([
{ pagePath: '/pages/home/index', text: 'Home' },
{ pagePath: '/pages/discover/index', text: 'Discover' },
{ pagePath: '/pages/profile/index', text: 'Profile' }
]);
await tabManager.switchToTab(1); // Switch to Discover tabCross-page communication patterns for data sharing and event handling.
// Event-based page communication
class PageCommunication {
private static eventBus = new Map<string, Function[]>();
static emit(event: string, data: any): void {
const listeners = this.eventBus.get(event) || [];
listeners.forEach(callback => {
try {
callback(data);
} catch (error) {
console.error('Page communication error:', error);
}
});
}
static on(event: string, callback: Function): void {
const listeners = this.eventBus.get(event) || [];
listeners.push(callback);
this.eventBus.set(event, listeners);
}
static off(event: string, callback?: Function): void {
if (!callback) {
this.eventBus.delete(event);
return;
}
const listeners = this.eventBus.get(event) || [];
const filtered = listeners.filter(cb => cb !== callback);
this.eventBus.set(event, filtered);
}
static once(event: string, callback: Function): void {
const onceCallback = (data: any) => {
callback(data);
this.off(event, onceCallback);
};
this.on(event, onceCallback);
}
}
// Usage in page components
function navigateWithCallback() {
// Listen for data from target page
PageCommunication.once('editor:save', (savedData) => {
console.log('Editor saved data:', savedData);
updateLocalData(savedData);
});
// Navigate to editor
navigateTo({
url: '/pages/editor/index?mode=create',
events: {
// Alternative event handling via navigateTo options
editorComplete: (data) => {
console.log('Editor completed:', data);
}
}
});
}
// In editor page
function saveAndReturn(data: any) {
// Emit event to parent page
PageCommunication.emit('editor:save', data);
// Navigate back
navigateBack();
}Navigation operations can fail due to invalid URLs, missing pages, or system restrictions.
// Comprehensive navigation error handling
async function safeNavigate(url: string, options?: Partial<NavigateOption>): Promise<boolean> {
try {
await navigateTo({ url, ...options });
return true;
} catch (error: any) {
console.error('Navigation error:', error);
// Handle specific error types
if (error.message?.includes('page not found')) {
await showModal({
title: 'Page Not Found',
content: 'The requested page does not exist.',
showCancel: false
});
} else if (error.message?.includes('too many pages')) {
await showModal({
title: 'Too Many Pages',
content: 'Too many pages open. Please close some pages and try again.',
showCancel: false
});
} else {
await showToast({
title: 'Navigation failed',
icon: 'error'
});
}
return false;
}
}
// Safe back navigation with fallback
async function safeNavigateBack(delta: number = 1, fallbackUrl?: string): Promise<void> {
try {
const pages = getCurrentPages();
if (pages.length <= delta) {
// Not enough pages to go back, use fallback or redirect to home
const target = fallbackUrl || '/pages/home/index';
await redirectTo({ url: target });
} else {
await navigateBack({ delta });
}
} catch (error) {
console.error('Navigate back failed:', error);
// Fallback to home page
await reLaunch({ url: '/pages/home/index' });
}
}interface CallbackOptions {
success?: (res: any) => void;
fail?: (err: any) => void;
complete?: (res: any) => void;
}
type AnimationType =
| 'slide-in-right' | 'slide-in-left' | 'slide-in-top' | 'slide-in-bottom'
| 'slide-out-right' | 'slide-out-left' | 'slide-out-top' | 'slide-out-bottom'
| 'fade-in' | 'fade-out'
| 'zoom-in' | 'zoom-out'
| 'zoom-fade-in' | 'zoom-fade-out'
| 'none';
interface NavigationError extends Error {
code?: string;
type?: 'page_not_found' | 'too_many_pages' | 'invalid_url' | 'permission_denied';
}Install with Tessl CLI
npx tessl i tessl/npm-tarojs--taro-h5