在鸿蒙HarmonyOS组件化开发中实现多模块路由跳转是解决业务模块间强耦合的核心环节。根据官方架构设计和最佳实践主要有以下几种主流方案方案一基于 Navigation 的系统路由表推荐这是鸿蒙官方推荐的跨包路由方案利用route_map.json实现模块间解耦。实现步骤在子模块HAR/HSP中配置路由表在子模块的resources/base/profile目录下创建route_map.json定义页面名称、源文件路径和对外导出的 Builder 函数。{ routerMap: [ { name: LoginPage, pageSourceFile: src/main/ets/pages/LoginPage.ets, buildFunction: LoginPageBuilder } ] }在module.json5中注册路由表module: { routerMap: $profile:route_map }在入口模块HAP中跳转主模块无需直接依赖子模块的页面代码只需通过NavPathStack的pushPathByName方法使用路由表中的name即可实现跳转。方案二基于 Router 的命名路由适用于传统的ohos.router体系。在子模块的页面组件上使用Entry({ routeName: CustomPage })进行命名主模块通过router.pushNamedRoute({ name: CustomPage })进行跳转。1. 目标模块共享包声明命名路由在需要被跳转的共享包如library中给Entry修饰的自定义组件配置routeName。// library/src/main/ets/pages/DetailPage.ets import { router } from kit.ArkUI; // 1. 使用 Entry 的 routeName 属性定义路由别名 Entry({ routeName: LibraryDetailPage }) Component export struct DetailPage { build() { Column() { Text(共享包详情页) .fontSize(24) Button(返回并传参) .onClick(() { // 返回上一页并携带自定义参数 router.back({ url: pages/Index, // 返回主模块的首页 params: { message: 操作成功 } }); }) } .width(100%) .height(100%) .justifyContent(FlexAlign.Center) } }2. 主模块HAP配置依赖与跳转在主模块中首先需要确保在oh-package.json5中引入了该共享包然后导入目标页面文件并执行跳转。// entry/src/main/ets/pages/Index.ets import { router } from kit.ArkUI; import { BusinessError } from kit.BasicServicesKit; // 2. 必须引入共享包中定义了命名路由的页面文件 import library/src/main/ets/pages/DetailPage; Entry Component struct Index { build() { Column() { Button(跳转到共享包页面) .onClick(() { try { // 3. 使用 pushNamedRoute 通过别名进行跳转 router.pushNamedRoute({ name: LibraryDetailPage, // 对应目标页面的 routeName params: { userId: 12345, data: { age: 20 } } }); } catch (err) { let error err as BusinessError; console.error(路由跳转失败code: ${error.code}, message: ${error.message}); } }) } .width(100%) .height(100%) .justifyContent(FlexAlign.Center) } }3. 目标模块接收参数在目标页面中可以通过生命周期如onPageShow获取主模块传递过来的参数。// 在 DetailPage.ets 的组件内部 onPageShow() { // 4. 获取传递过来的参数对象 const params router.getParams() as Recordstring, Object; if (params) { const userId params[userId] as string; console.info(接收到主模块传递的用户ID: ${userId}); } }方案三引入第三方路由框架高阶解耦对于大型复杂项目可以使用成熟的第三方路由框架如HMRouter、ZRouter通过注解或编译插件自动生成路由表进一步降低维护成本。以HMRouter为例安装依赖通过 ohpm 安装hadss/hmrouter核心库及编译插件hadss/hmrouter-plugin。配置编译插件在工程根目录的hvigor/hvigor-config.json5中配置插件依赖并在hvigorfile.ts中启用appPlugin。初始化与定义容器在UIAbility的onCreate中调用HMRouterMgr.init()初始化框架并在首页使用HMNavigation作为路由容器。注解声明与跳转在目标页面使用HMRouter({ pageUrl: PageB })注解声明路由信息跳转时直接通过HMRouterMgr.push(PageB)即可完成跨模块通信彻底告别硬编码依赖。1. 安装依赖与配置编译插件首先在工程的依赖配置文件中引入核心库并在构建脚本中启用编译插件。// oh-package.json5 { dependencies: { hadss/hmrouter: ^1.0.0 // 引入核心运行时库 } }// 工程根目录 hvigorfile.ts import { appTasks } from ohos/hvigor-ohos-plugin; import { appPlugin } from hadss/hmrouter-plugin; // 引入编译插件 export default { system: appTasks, plugins: [appPlugin()] // 启用插件编译时自动扫描注解并生成路由表 };2. 框架初始化与根容器配置在应用启动时初始化框架并在首页配置HMNavigation作为全局路由栈容器。// EntryAbility.ets import { HMRouterMgr } from hadss/hmrouter; export default class EntryAbility extends UIAbility { onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { // 初始化路由框架 HMRouterMgr.init({ context: this.context }); } }// pages/Index.ets (首页) import { HMNavigation } from hadss/hmrouter; Entry Component struct Index { build() { Column() { // 使用 HMNavigation 作为路由根容器 HMNavigation({ navigationId: MainNavigation, // 导航栈唯一标识 homePageUrl: HomePage // 首页路由标识 }) } .height(100%) .width(100%) } }3. 注解声明页面与跨模块跳转在目标页面使用HMRouter注解声明路由跳转时只需传递字符串标识无需import目标页面的代码。目标页面如位于子模块 ModuleB// ModuleB/src/main/ets/pages/DetailPage.ets import { HMRouter, HMRouterMgr } from hadss/hmrouter; HMRouter({ pageUrl: ProductDetail // 声明唯一的路由标识 }) Component export struct DetailPage { build() { Column() { Text(商品详情页) Button(返回并传参) .onClick(() { // 返回上一页并携带数据 HMRouterMgr.pop({ param: { action: refresh_list } }); }) } } }发起跳转的页面如位于主模块 ModuleA// ModuleA/src/main/ets/pages/HomePage.ets import { HMRouterMgr } from hadss/hmrouter; HMRouter({ pageUrl: HomePage }) Component export struct HomePage { build() { Column() { Button(跳转到商品详情) .onClick(() { // 跨模块跳转无需 import DetailPage HMRouterMgr.push({ pageUrl: ProductDetail, // 匹配目标页面的 pageUrl param: { productId: 10086, source: home } }); }) } } }4. 目标页面接收参数在目标页面中可以通过HMRouterMgr.getCurrentParam()安全地获取跳转时传递的参数// 在 DetailPage.ets 中 aboutToAppear() { // 获取传递过来的参数 const params HMRouterMgr.getCurrentParam() as Recordstring, Object; if (params) { const productId params[productId] as string; console.info(接收到商品ID: ${productId}); } }一、 路由拦截与全局鉴权Navigation Guards在大型应用中很多页面如订单详情、个人中心需要登录态或特定权限。如果每个页面都去写鉴权逻辑会导致严重的代码冗余。我们需要在路由层实现全局拦截。借助鸿蒙原生的NavPathStack拦截器或者第三方框架如fw/router、ZRouter的全局拦截器机制我们可以在页面跳转前进行统一校验// 示例基于 NavPathStack 的路由拦截器 const pathStack new NavPathStack(); pathStack.setInterception({ willShow: (navDestinationContext: NavDestinationContext) { const targetRoute navDestinationContext.pathInfo.name; // 定义需要鉴权的路由白名单/黑名单 const requireAuthRoutes [OrderDetail, UserProfile]; if (requireAuthRoutes.includes(targetRoute)) { const isLoggedIn AppStorage.getboolean(isLoggedIn) ?? false; if (!isLoggedIn) { // 拦截跳转重定向到登录页并携带原始目标路由作为参数 pathStack.pushPathByName(LoginPage, { redirect: targetRoute }); return false; // 阻止当前跳转 } } return true; // 允许跳转 } });二、 跨模块通信与状态共享路由解耦后模块 A 跳转到模块 B如果模块 B 需要模块 A 的数据或者模块 B 执行完操作后需要通知模块 A 刷新直接互相import会破坏组件化架构。1. 参数传递与返回值利用NavPathStack的pushPath传递参数并结合pop()的返回值实现跨模块通信// 模块 A发起跳转并接收返回值 pathStack.pushPathByName(ModuleB_Page, { itemId: 123 }).then((result) { if (result refresh_needed) { this.refreshList(); // 模块 B 操作完成后刷新模块 A 的列表 } }); // 模块 B处理完毕并返回结果 this.pathStack.pop({ action: refresh_needed });2. 全局状态管理对于跨模块的共享数据如用户信息、全局配置应摒弃路由参数传递统一使用鸿蒙的AppStorage或PersistentStorage// 任何模块均可读写 AppStorage.setOrCreate(global_user_info, userInfo);三、 路由性能优化与懒加载当应用包含数十个甚至上百个分包HAR/HSP时启动时加载所有路由表和页面资源会导致严重的性能瓶颈。1. 页面级懒加载Lazy Loading结合 ArkUI 的声明式渲染特性对于 Tab 页面或复杂的嵌套路由使用if-else条件渲染实现按需加载避免一次性创建所有组件实例build() { Column() { if (this.currentTabIndex 0) { HomeTabContent() } else if (this.currentTabIndex 1) { // 只有切换到发现页时才真正加载该模块的 UI 树 DiscoverTabContent() } } }2. 动态导入与按需加载对于超大型应用可以使用动态import()语法在真正触发路由跳转时才去加载对应的 HAR/HSP 模块从而极大缩短冷启动时间。四、 渐进式迁移策略从 Router 到 Navigation如果是一个历史包袱较重的老项目正在从传统的ohos.router向Navigation体系迁移切忌“一刀切”式重构。推荐采用兼容层Adapter模式// 封装统一的路由分发器 export function smartNavigate(url: string, params?: object) { if (isNavigationMode) { // 新架构使用 NavPathStack navPathStack.pushPathByName(url, params); } else { // 老架构使用传统 Router router.pushUrl({ url: url, params: params }); } }通过这种策略可以优先将非核心、低风险的新增页面接入Navigation路由表待核心页面如首页、登录页充分测试后再逐步迁移确保线上版本的绝对稳定。