# EasyRouter **Repository Path**: pengyoucongcode/EasyRouter ## Basic Information - **Project Name**: EasyRouter - **Description**: 以动态加载为核心,实现自定义路由管理器,配合 ArkUI 的 Navigation 进行使用 - **Primary Language**: Unknown - **License**: MulanPSL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-07-19 - **Last Updated**: 2025-08-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # EasyRouter EasyRouter 是一个用于简化页面路由管理的工具库,适用于 HarmonyOS 应用开发。它提供了便捷的路由注册、页面跳转和参数传递功能,帮助开发者更高效地管理应用导航逻辑。 ## 1、获取本工具 你可以通过以下方式获取 EasyRouter: - 通过 Gitee 仓库克隆项目: ```bash git clone https://gitee.com/pengyoucongcode/EasyRouter.git ``` - 或者将库作为模块引入到你的项目中(请参考项目配置文件 `oh-package.json5`)。 ## 2、路由配置 ### 2.1、注册路由 在体验跨模块页面跳转之前,必须将目标页面进行路由注册,完成这一步,建议在 entry 模块的适当位置新建一个 `RouterInfoConstant`,并在类体中定义类似如下的静态只读变量: ```typescript import { RouterInfo } from "lib_easyrouter"; export class RouterInfoConstant { static readonly FeatureTestMainPage: RouterInfo = new RouterInfo("/feature_test/main_page", "FeatureTestMainPage", "feature_test"); } ``` 其中,RouterInfo 的原型如下: ```typescript export class RouterInfo { url: string = ""; pageName: string = ""; moduleName: string = ""; constructor(url: string, pageName: string, moduleName: string) { this.url = url; this.pageName = pageName; this.moduleName = moduleName; } } ``` 同样的,在 entry 模块的适当位置新建一个 ArkTS 脚本,编写如下内容: ```typescript import { RouterRegister } from "lib_easyrouter"; import { RouterInfoConstant } from "../constants/RouterInfoConstant"; export class EntryUtil { static initRouterInfoRegister() { RouterRegister.register(RouterInfoConstant.FeatureTestMainPage); } } ``` 并将 initRouterInfoRegister 方法在 EntryAbility 的生命周期函数 onCreate 中进行调用: ```typescript onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); // hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate'); Logger.init(this.context); Logger.info(`onCreate`, TAG) Logger.info(`launchParam: ${JSON.stringify(launchParam)}`, TAG) Logger.info(`want: ${JSON.stringify(want)}`, TAG) EntryUtil.initRouterInfoRegister(); } ``` 为了保证跨模块路由功能生效,需要将目标页面所在的模块设置成 `runtimeOnly` 类型,具体方式就是通过修改 entry 模块的 build-profile.json5 文件中的 buildOption 来实现,例如下面: ```json { "apiType": "stageMode", "buildOption": { "arkOptions": { "runtimeOnly": { "packages": [ "feature_test" ] } } } } ``` 其中,packages 数组中填写的模块名,要保持同 entry 模块的 oh-package.json5 文件中的 dependences 中的一致: ```json { "name": "entry", "version": "1.0.0", "description": "Please describe the basic information.", "main": "", "author": "", "license": "", "dependencies": { "lib_easyrouter": "file:../lib_EasyRouter", "feature_test": "file:../feature_test" } } ``` ### 2.2、注册页面 一个路由对应一个具体的页面,这个具体页面通常由使用 `@Component` 装饰的结构体定义,而要让该页面可以通过跨模块路由器进行导航,就必须将其注册到路由器的路由栈中,具体就是使用类似如下的代码: ```typescript @Builder export function getPage(param: ESObject): void { MainPage(param) } EasyRouter.registerRouterPage(RouterRegister.getRouterInfoByUrl("/feature_test/main_page"), wrapBuilder(getPage)) ``` ### 2.3、分流锚定源代码 每个页面都是由具体的源代码定义的,而每个页面代码都放在模块的不同目录下,而模块下的目录结构,对于 EasyRouter 来说,都是透明的,因此,为了正确加载对应的页面源码,就需要在模块的 **Index.ets** 文件中定义一个 `harInit` 方法,去负责分流锚定源码: ```typescript import { RouterRegister } from 'lib_easyrouter'; export { MainPage } from './src/main/ets/components/MainPage'; export function harInit(name: string) { switch(name) { case RouterRegister.getPageNameByUrl("/feature_test/main_page"): import("./src/main/ets/components/MainPage"); break; default: break; } } ``` ## 3、路由使用 ### 3.1、页面跳转 经过上面的路由配置之后,就可以开始进行路由使用了,也就是进行页面导航,首先,在应用起始页对应的 ArkTS 脚本中,使用 Navigation 组件创建一个页面容器: ```typescript @Entry @Component struct Index { @State message: string = 'Hello World'; private prompter: PromptAction = this.getUIContext().getPromptAction(); @Provide("mainPathStack") mainPathStack: NavPathStack = new NavPathStack(); private isSecondPressBack: boolean = false; aboutToAppear(): void { EasyRouter.createNavPathStack(this.mainPathStack) } @Builder navDestinationBuilder(name: string, param?: object) { NavDestination(){ EasyRouter.getBuilder(name).builder(param); }.hideTitleBar(true) } onBackPress(): boolean | void { if (this.isSecondPressBack) { return false; } else { this.isSecondPressBack = true; setTimeout(() => {this.isSecondPressBack = false; }, 1000); this.prompter.showToast({ message: "再滑一次退出", duration: 1800 }); return true; } } build() { Navigation(this.mainPathStack) { Column({space: 25}) { Text(this.message) .fontSize(50) .fontWeight(FontWeight.Bold) Button(){ Text("跳到下一页").fontSize(20).fontWeight(FontWeight.Bold); }.width("80%").height(50).type(ButtonType.Normal) .onClick(() => { EasyRouter.pushUrl(RouterRegister.getRouterInfoByUrl("/feature_test/main_page")); }) } .width('100%').height("100%") .alignItems(HorizontalAlign.Center) .justifyContent(FlexAlign.Center) } .mode(NavigationMode.Stack) .hideTitleBar(true) .navDestination(this.navDestinationBuilder) } } ``` 而目标页面可以定义类似如下: ```typescript const TAG = "[FeatureTestMainPage]" @Component export struct MainPage { @State message: string = 'Feature Test Main Page'; build() { Column() { Text(this.message) .fontSize(50) .fontWeight(FontWeight.Bold) Button(){ Text("返回上一页").fontSize(20).fontWeight(FontWeight.Bold); }.width("80%").height(50).type(ButtonType.Normal) .onClick(() => { EasyRouter.back() }) } .width('100%').height("100%") .alignItems(HorizontalAlign.Center) .justifyContent(FlexAlign.Center) } } ``` 这样就完成了页面的进入和退出。 ### 3.2、路由传参 在实际开发过程中,打开目标页面的同时,传入一些数据是常见的操作,而 EasyRouter 对此提供了支持。目前,EasyRouter 只支持传递对象类型的数据,所以,如果你想通过路由进行数据传递,那么应当事先定义好一个对象类型,比如下面这种 RoutParam: ```typescript class RouteParam { message: string = ""; data: ESObject|null = null; constructor(message: string, data?: ESObject) { this.message = message; this.data = data; } } ``` 然后,只需将打开页面的按钮的处理函数修改如下模样: ```typescript const param: RouteParam = new RouteParam("测试路由传递数据", this.getUIContext().getWindowName()); EasyRouter.pushUrl(RouterRegister.getRouterInfoByUrl("/feature_test/main_page"), param); ``` 便能完成数据的传入,相对应的,目标页面就需要加上读取数据的代码,通常就是放在 aboutToAppear 函数中: ```typescript @State text: string = "[]" aboutToAppear(): void { const param = EasyRouter.getParams(RouterRegister.getRouterInfoByUrl("/feature_test/main_page")); Logger.info(JSON.stringify(param), TAG); const routeParam: RouteParam = param[0] as RouteParam; this.text = routeParam.message + "\n" + routeParam.data; } ``` 需要注意的是,EasyRouter.getParams() 返回的是一组数据,而不是单独一个。 更为详细的代码,大家可以前往本工具对应的代码工程进行浏览。