Skip to content

导航系统

概述

导航系统提供了统一的页面导航和路由管理功能。

核心概念

路由注册

在模块中注册路由:

typescript
/**
 * 用户模块
 * 实现 FeatureModule 接口,支持自动注册
 */
export class UserModule implements FeatureModule {
  /**
   * 注册路由
   * @param registry 路由注册器
   */
  registerRoutes(registry: RouteRegistry): void {
    // 注册用户页路由
    registry.register(UserRoutes.Profile, profileNavBuilderWrapper);
  }
}

页面导航

使用 NavigationService 进行页面导航:

typescript
import { NavigationService } from "@core/navigation";

// 导航到指定页面
NavigationService.push("user/profile", { userId: "123" });

// 返回上一页
NavigationService.pop();

// 替换当前页面
NavigationService.replace("user/settings");

// 返回到根页面
NavigationService.popToRoot();

路由参数

传递参数

typescript
NavigationService.push("user/profile", {
  userId: "123",
  from: "main"
});

接收参数

typescript
@Entry
@Component
struct UserProfilePage {
  @State userId: string = "";

  aboutToAppear(): void {
    // 获取路由参数
    const params = NavigationService.getParams();
    this.userId = params.userId;
  }

  build() {
    Column() {
      Text(`用户 ID: ${this.userId}`);
    }
  }
}

路由拦截

登录拦截

typescript
NavigationService.addInterceptor((to, from) => {
  if (to.path.startsWith("user/") && !isLoggedIn()) {
    // 未登录,跳转到登录页
    NavigationService.push("auth/login");
    return false;  // 阻止导航
  }
  return true;  // 允许导航
});

权限拦截

typescript
NavigationService.addInterceptor((to, from) => {
  const requiredPermission = to.meta?.permission;
  if (requiredPermission && !hasPermission(requiredPermission)) {
    // 无权限,显示提示或跳转到无权限页面
    showToast("您没有访问权限");
    return false;
  }
  return true;
});

全局拦截器

typescript
// 添加全局前置拦截器
NavigationService.beforeEach((to, from, next) => {
  console.log(`导航从 ${from.path} 到 ${to.path}`);

  // 检查登录状态
  if (to.meta?.requiresAuth && !isLoggedIn()) {
    next({ path: "auth/login", query: { redirect: to.path } });
    return;
  }

  // 检查权限
  if (to.meta?.permission && !hasPermission(to.meta.permission)) {
    showToast("无权限访问");
    next(false);
    return;
  }

  next();
});

// 添加全局后置拦截器
NavigationService.afterEach((to, from) => {
  // 记录页面访问日志
  logPageView(to.path);

  // 更新页面标题
  document.title = to.meta?.title || "默认标题";
});

路由守卫

typescript
/**
 * 认证模块
 * 实现 FeatureModule 接口,支持自动注册
 */
export class AuthModule implements FeatureModule {
  /**
   * 注册路由守卫
   * @param navigationService 导航服务
   */
  registerGuards(navigationService: NavigationService): void {
    // 注册认证守卫(保护需要登录的页面)
    navigationService.registerGuard(new AuthGuard());
  }
}

/**
 * 认证路由守卫
 * 保护需要登录才能访问的页面
 */
class AuthGuard implements RouteGuard {
  /**
   * 守卫名称
   */
  readonly name: string = 'AuthGuard';

  /**
   * 守卫优先级(数字越大优先级越高)
   */
  readonly priority: number = 100;

  /**
   * 检查是否可以激活路由
   * @param context 路由上下文
   * @returns 是否允许导航
   */
  canActivate(context: RouteContext): boolean | Promise<boolean> {
    return false;
  }

  /**
   * 守卫拒绝时的回调
   * @param context 路由上下文
   * @param result 守卫结果
   */
  onReject(context: RouteContext, result: GuardResult): void {
    // 跳转到登录页
  }
}

最佳实践

1. 统一路由管理

在模块初始化时统一注册路由:

typescript
/**
 * 用户模块
 * 实现 FeatureModule 接口,支持自动注册
 */
export class UserModule implements FeatureModule {
  /**
   * 注册路由
   * @param registry 路由注册器
   */
  registerRoutes(registry: RouteRegistry): void {
    // 注册用户页路由
    registry.register(UserRoutes.Profile, profileNavBuilderWrapper);
  }

  /**
   * 注册路由守卫
   * @param navigationService 导航服务
   */
  registerGuards(navigationService: NavigationService): void {
    // 用户模块不需要额外的守卫,依赖 auth 模块的认证守卫
  }
}

2. 路由命名规范

使用 模块名/页面名 的格式命名路由:

typescript
// 推荐
"user/profile"
"auth/login"
"main/home"

// 不推荐
"profile"
"login"
"home"

3. 参数类型安全

定义参数接口确保类型安全:

typescript
interface UserProfileParams {
  userId: string;
  from?: string;
}

NavigationService.push<UserProfileParams>("user/profile", {
  userId: "123",
  from: "main"
});

注意事项

  1. 路由注册:确保在使用前注册路由
  2. 参数传递:注意参数的类型和必填性
  3. 内存管理:及时清理不需要的页面栈

下一步