CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-tarojs--taro-h5

H5端API库,为Taro跨端开发框架提供Web/H5端的API实现

Pending
Overview
Eval results
Files

navigation.mddocs/

Route Navigation APIs

Page navigation and routing capabilities integrated with @tarojs/router for single-page application navigation, providing programmatic control over page transitions and history management.

Capabilities

Page Navigation

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'
});

Router Information

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;
}

Advanced Navigation Patterns

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 tab

Page Communication

Cross-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();
}

Error Handling

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' });
  }
}

Types

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

docs

canvas.md

core-framework.md

device.md

dom-query.md

index.md

location.md

media.md

navigation.md

network.md

storage.md

system-info.md

ui-interactions.md

tile.json