一、背景
公司鸿蒙项目采用壳工程 + 功能模块拆分为独立工程的架构模式,既实现代码解耦,也方便多团队并行开发,但独立工程之间无法直接引用源码,那就要考虑如何实现 "主工程按钮点击跳转到功能工程的页面"问题,通过以下案例来实现这个思路步骤
二、前置了解
先了解几个鸿蒙的核心概念
1、HAR 包:鸿蒙的 "模块归档包",包含代码、资源、依赖的独立单元,是跨工程依赖的唯一载体;
2、跨工程依赖:主工程通过依赖功能工程的 HAR 包 / 本地模块,间接访问其组件;
3、NavPathStack:鸿蒙原生全局路由栈,是承载所有页面(包括跨工程页面)的容器。
三、具体流程
案例:lucyTest工程→loginTest 工程 login模块,跨工程跳转
主要分为三部分:发送方(lucyTest 主工程)配置,接收方(loginTest 登录工程)配置,跳转逻辑实现
3.1、接收方
3.1.1、准备可被跳转的模块
在loginTest工程内新建login模块可被其他工程依赖,并提供可跳转的页面(loginPage.ets)
目的:定义跨工程跳转的目标页面组件,后续通过路由映射让主工程识别。

3.1.2、配置路由表
在loginTest的login模块中,创建route_map.json
目的 :鸿蒙路由系统通过route_map.json识别页面的 "唯一标识(name)" 与 "渲染入口",是跨工程跳转的 "页面身份证"。
具体使用方法可参考此文章:https://blog.csdn.net/weixin_71403100/article/details/154455692?spm=1001.2014.3001.5502
TypeScript
{
"routerMap": [
{
"name": "loginPage",
"pageSourceFile": "src/main/ets/_generated/BuilderMap.ets",
"buildFunction": "loginPageBuilder",
"data": {
"needLogin": "false"
}
}
]
}
3.1.3、生成页面构建器:统一页面入口
在loginTest的login模块中,创建BuilderMap.ets,定义页面的构建函数
目的 :将页面组件封装为@Builder函数,匹配route_map.json中的buildFunction,让路由系统能直接调用渲染页面。
备注:当路由页面少时这一步可以直接放到第一步中,当大型项目页面多时,建议抽成一个文件,在index中统一导出

3.1.4、导出模块入口:对外暴露能力
在login 模块 index.ets 导出目标组件
目的 :主工程依赖模块后,通过index.ets统一访问模块的能力(页面、方法)。
TypeScript
//路径: /loginTest/login/Index.ets
export * from './src/main/ets/_generated/BuilderMap'
3.1.5、将login模块打包为HAR包

3.2、发送方
3.2.1、引入 login 模块:本地依赖 / HAR 包依赖二选一
方式1:本地路径依赖(工程在同一目录下)
1、在lucyTest的build-profile.json5中注册login模块:

2、在lucyTest的oh-package.json5中声明依赖:

方式 2:HAR 包依赖
将login模块的 HAR 包放入lucyTest的libs目录,再在oh-package.json5中依赖:
执行ohpm install安装依赖,主工程即可访问login模块的能力。

3.2.2 初始化 login 模块:动态导入 + 传递上下文
在lucyTest的EntryAbility.ets中,动态导入login模块并执行初始化(传递主工程上下文):
**备注:**这一步我理解是跨工程模块的核心,也是"通信桥梁",如果无它,login模块既无法访问系统资源,也无法和主工程协同工作,最终导致跳转失败

3.2.3、配置全局路由栈:承载跨工程页面的容器
在lucyTest的跳转页面(如Index.ets)中,创建全局唯一的 NavPathStack(鸿蒙原生路由栈,所有页面都需通过它跳转):
TypeScript
// lucyTest/entry/src/main/ets/pages/Index.ets
@Entry
@Component
struct Index {
// 全局路由栈:承载主工程+跨工程的页面
private globalNavStack: NavPathStack = new NavPathStack();
build() {
Column(){
// Navigation绑定全局路由栈(页面跳转的容器)
Navigation(this.globalNavStack){
// 跳转按钮
Button('跳转到login组件')
.onClick(()=>{
// 后续实现跳转逻辑
})
}
.height('100%')
.width('100%')
}
}
}
3.3、实现跨工程跳转逻辑
在lucyTest的Index.ets按钮点击事件中,调用NavPathStack.pushPathByName,通过loginPage路由名称跳转:
目的 :通过route_map.json中注册的loginPage名称,让路由系统找到对应的页面构建函数,渲染跨工程的loginPage组件。
TypeScript
// lucyTest/entry/src/main/ets/pages/Index.ets
Button('跳转到login组件')
.onClick(()=>{
// 跳转到login模块的loginPage页面
this.globalNavStack.pushPathByName('loginPage', null, false);
})
四、技能总结
主要使用到:
Navigation路由导航
HAR包跨工程依赖
动态导入 + harInit
五、会遇到的坑
以下是因为粗心大意而遇到的坑,总结下以免后续再犯
1、主工程找不到 login 模块
检查build-profile.json5/oh-package.json5的路径是否正确;执行ohpm install
2、跳转过去是个空白
检查路由表信息的配置项是否正确,检查是否绑定NavPathStack
3、harInit方法未找到
检查login模块的index.ets是否导出了harInit