TheRouter
鸿蒙版是货拉拉基于HMRouter深度定制的开源路由框架,提供了 Android、iOS、Harmony 三端高一致性使用,在支持平台化应用实现组件化、跨模块调用、动态化等功能的集成等功能基础上,支持动态路由下发、编译时安全检查、路由Path一对多等高度动态能力。
Github: https://github.com/HuolalaTech/hll-wp-therouter-harmony/
官网:http://therouter.cn/
0、开始之前
如果你的是新项目,请先记住一点:plugin、router 两个依赖的版本号必须保持一致,请继续往下看接入步骤。
0.1、查看最新版本
TheRouter 的版本分为两种,稳定版和 rc版,一般不追求新功能我们就用稳定版就行,可以在官网看到最新的版本号和各种版本的说明:https://therouter.cn/docs/2022/09/06/01
一、接入
在工程根目录命令行引入依赖库和插件库(必须全部依赖,不能只使用其中一个)。
// 引入代码库依赖
ohpm i @therouter/library
// 引入插件依赖
npm i @therouter/plugin
第一步:接入编译插件
- 打开项目根目录的
hvigor/hvigor-config.json5
,检查dependencies
中是否已经加入了依赖,一般为"@therouter/plugin": "x.x.x"
。 - 打开工程 所有 模块(hsp、hap、har)的
hvigorfile.ts
文件。 - 在
plugins
中加入如下对应的依赖
// 如果是 hap,则类似如下依赖
import { hapPlugin } from "@therouter/plugin";
export default {
plugins: [hapPlugin()]
}
// 如果是 har,则类似如下依赖
import { harPlugin } from "@therouter/plugin";
export default {
plugins: [harPlugin()]
}
// 如果是 hsp,则类似如下依赖
import { hspPlugin } from "@therouter/plugin";
export default {
plugins: [hspPlugin()]
}
第二步:检查依赖是否引入
- 打开 工程根目录 的
oh-package.json5
文件。 - 检查
dependencies
中,是否已经加入了依赖,一般为:"@therouter/library": "x.x.x"
二、使用
2.1、 初始化
在项目入口的 UIAbility
的 onCreate()
中加入如下代码:
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
TheRouter.init(this.context);
}
2.2、 定义页面容器
TheRouter 按照华为推荐方案,基于系统 Navigation 实现,所以必须在页面中定义一个容器项 TheRouterPage
,建议创建一个完全新的类作为入口并在 /resources/base/profile/main_pages.json
中配置这个类,复制如下代码:
import { TheRouterPage } from '@therouter/library';
@Entry
@Component
struct Index {
build() {
RelativeContainer() {
TheRouterPage({
stackId: 'XXXX', //【必传】可以自定义当前stack的名字,每个stack必须唯一
root: 'path' // 【必传】当前应用的首页 path,推荐按照一定格式定义页面path
// 还有很多可选参数,详情请见文档
});
}
.height('100%')
.width('100%')
}
}
2.3、声明路由
给需要跳转的页面加上路由表声明
@Route({path : "http://therouter.com/home"})
export struct HomePage {
xxx
}
2.4、发起跳转
在需要跳转页面的位置调用如下代码:
TheRouter
.build("http://therouter.com/home")
.withString('k', 'v') // 向落地页传参数(如果没参数,可不调用)
.with({ hello: 'world' }) // 另一种方式传参
.navigation()
2.5、获取页面传参
接收有两种形式:
- 通过注解自动接收,默认支持 String 和8种基本数据类型,也支持自定义对象的解析
- 通过代码从路由中获取
使用注解接收对象时,必须调用 TheRouter.inject(this) 。
// 第一种:使用注解自动填充
// 允许解析成8种基本数据类型或对应封装类
@Autowired()
key1 : string = ''
// 允许自定义传参key,如果不传默认是变量名作为key
@Autowired('hello')
key1 : string = ''
// 使用注解接收对象时,必须调用,建议放在 aboutToApper() 中调用。
TheRouter.inject(this)
// 第二种:通过代码从路由中获取
// 可以在任何方法中调用,getCurrentParam() 返回值是个ESObject
const v = TheRouter.getCurrentParam()['k'];
三、问题排查万能公式
在使用过程中,如果发现服务无法调用,或返回为空的时候。通常的排查方式都是以下三步:
-
首先观察接入环境。插件是否和依赖库版本一致,插件是否生效了。在我们内部使用的过程中,经常发现,
oh-package.json5
中引入的明明是新版本,但是实际编译时使用的还是老版本,猜测应该是构建工具的问题。在TheRouter
编译时,日志的第一行就会有当前编译实际使用的版本号,如果和你预期不一致时,需要再执行一下命令行:// 引入代码库依赖 ohpm i @therouter/library // 引入插件依赖 npm i @therouter/plugin
-
上一步排查完依然无法调用时,就要考虑一下是不是代码使用姿势问题了。比如添加
@ServiceProvider
的服务提供者必须实现IServiceProvider
接口。服务提供者注解参数里面的serviceName
是不是和使用方传入的一致。注:如果多次添加重复serviceName,框架会保证安全,在编译时报错。 -
如果上两步都不能解决你的问题,那就需要进源码通过断点调试进一步明确问题出在哪里了。首先从
TheRouter.init()
开始找,看看路由表读取是否正确,再看服务Map里面是否有记录成功,再看调用的时候传入的是否正确,一步一步排查。
四、鸿蒙路由源码调试步骤
4.1、clone 仓库
使用命令行:
git clone git@github.com:HuolalaTech/hll-wp-therouter-harmony.git
4.2、创建 build-profile
在项目根目录中,新建一个名为 build-profile.json5
的文件,文件内加入如下内容。
{
"app": {
"signingConfigs": [
// 签名部分需要手动从官网获取自己的开发者信息
],
"products": [
{
"name": "default",
"signingConfig": "xxxxx填上面的签名信息",
"compatibleSdkVersion": "可根据自己SDK情况填写",
"runtimeOS": "HarmonyOS",
"buildOption": {
"strictMode": {
"caseSensitiveCheck": true,
"useNormalizedOHMUrl": true
}
}
}
],
"buildModeSet": [
{
"name": "debug",
},
{
"name": "release"
}
]
},
"modules": [
{
"name": "entry",
"srcPath": "./entry",
"targets": [
{
"name": "default",
"applyToProducts": [
"default"
]
}
]
},
{
"name": "therouter",
"srcPath": "./therouter"
},
{
"name": "business_a",
"srcPath": "./business_a"
},
{
"name": "business_b",
"srcPath": "./business_b"
},
{
"name": "base",
"srcPath": "./base"
}
]
}
4.3、创建 hvigor 构建环境
在工程根目录新建一个名为 hvigor
的文件夹
文件夹内新建一个名为 hvigor-config.json5
的文件,文件内加入如下内容:
{
"modelVersion": "根据实际情况填写版本号",
"dependencies": {
"@therouter/plugin": "根据实际情况填写版本号"
},
"execution": {
// "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | false ]. Default: "normal" */
// "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */
// "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */
// "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */
// "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */
},
"logging": {
// "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */
},
"debugging": {
// "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */
},
"nodeOptions": {
// "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/
// "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/
}
}