当前位置: 首页 > news >正文

路由框架:实现页面解耦与拦截器的路由库(230)

在鸿蒙(HarmonyOS)原生开发中,随着应用规模的扩大,传统的硬编码路由会导致模块间高度耦合。为了实现页面解耦、统一拦截(如登录校验)以及跨模块通信,开发者通常会引入成熟的路由框架。

目前鸿蒙生态中最具代表性的路由方案是官方开源的HMRouter,以及社区广泛使用的ZRouterTheRouter

一、 官方开源方案:HMRouter

HMRouter 是鸿蒙官方推出的路由管理组件,旨在简化应用内原生页面的跳转逻辑。它底层封装了系统的NavigationNavDestinationNavPathStack,通过编译期注解处理器自动生成路由表,实现业务与路由的解耦。

  • 注解驱动与声明式路由:通过@HMRouter装饰器声明路由路径,支持字符串常量定义,并兼容 HAR/HSP/HAP 模块化方案。
  • 强大的拦截器机制:支持全局拦截、单页面拦截以及跳转时一次性拦截。开发者可以轻松实现未登录拦截、权限校验等逻辑。
  • 生命周期与转场动画:提供全局与单页面的生命周期回调,并内置了 slide、fade、scale 等转场动画,支持交互式动画配置。
  • 服务路由(Service Route):除了页面跳转,HMRouter 还支持通过@HMService注册服务,实现跨模块的方法调用与解耦。
5. 官方 HMRouter 初始化与页面声明实战 场景:在应用启动时初始化路由框架,并通过注解声明式定义页面路由,实现跨模块的无缝跳转。 typescript 编辑 // 1. 在 EntryAbility 中初始化路由框架 import { HMRouterMgr } from '@hadss/hmrouter'; export default class EntryAbility extends UIAbility { onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { HMRouterMgr.init({ context: this.context }); } } // 2. 使用注解声明页面路由(无需手动包裹 NavDestination) import { HMRouter, HMRouterMgr } from '@hadss/hmrouter'; @HMRouter({ pageUrl: 'page/detail' }) @Component export struct DetailPage { // 自动获取路由传递的参数 @State param: Object | null = HMRouterMgr.getCurrentParam(); build() { Column() { Text(`详情页参数: ${JSON.stringify(this.param)}`).fontSize(18); Button('返回并携带结果').onClick(() => { // 返回上一页并传递结果 HMRouterMgr.pop({ param: { status: 'success' } }); }); } .width('100%') .height('100%') .justifyContent(FlexAlign.Center); } } 6. 全局拦截器实战:未登录自动重定向 场景:在跳转到个人中心等受保护页面时,全局拦截器自动检查登录状态。若未登录,则拦截原始请求并重定向至登录页。 typescript 编辑 import { HMRouterMgr, HMInterceptorAction, HMInterceptorInfo } from '@hadss/hmrouter'; // 定义全局登录拦截器 export class LoginGlobalInterceptor { handle(info: HMInterceptorInfo): HMInterceptorAction { const isLogin = false; // 模拟未登录状态 if (!isLogin && info.targetName === 'page/profile') { // 拦截原始跳转,重定向至登录页,并携带目标页URL以便登录后返回 HMRouterMgr.push({ pageUrl: 'page/login', param: { targetUrl: info.targetName }, skipAllInterceptor: true // 登录页跳转跳过拦截器,防止死循环 }); return HMInterceptorAction.DO_REJECT; // 拒绝原始跳转 } return HMInterceptorAction.DO_NEXT; // 放行,继续执行下一个拦截器或跳转 } } 7. 跨模块服务路由:接口与实现解耦 场景:基础模块需要调用业务模块的方法(如获取用户信息),但不允许基础模块直接依赖业务模块。通过 @HMService 实现服务注册与发现。 typescript 编辑 // 1. 在业务模块中注册服务 import { HMService } from '@hadss/hmrouter'; export class UserService { @HMService({ serviceName: 'IUserService', singleton: true }) getUserInfo(): string { return '当前用户: HarmonyOS Dev'; } } // 2. 在基础模块中获取服务并调用(无需 import 实现类) // 通过 HMRouterMgr 获取服务实例 const userService = HMRouterMgr.getService('IUserService') as UserService; console.info(userService.getUserInfo());

二、 社区进阶方案:ZRouter 与 TheRouter

  • ZRouter:同样基于自定义注解和代码生成实现。它提供了极其优雅的链式调用 API(如ZRouter.getInstance().push("Login")),其全局拦截器(GlobalNavigateInterceptor)支持在onNavigate中根据页面的needLogin属性进行重定向和参数替换。
  • TheRouter:针对超大型项目的模块化协作,TheRouter 通过动态路由表和ServiceProvider机制,完美解决了复杂的跨模块依赖注入与服务发现痛点。
import { TheRouter, Route, Autowired } from '@therouter/library'; // 1. 声明路由并自动注入参数 @Route({ path: 'http://therouter.com/home' }) @Component export struct HomePage { @Autowired() userId: string = ''; aboutToAppear(): void { // 使用注解接收对象时,必须调用 inject TheRouter.inject(this); } build() { Column() { Text(`当前用户ID: ${this.userId}`).fontSize(18); } } } // 2. 发起跳转并传递参数 TheRouter .build('http://therouter.com/home') .withString('userId', 'U12345') .navigation();

三、 核心能力:路由拦截器(Interceptor)

拦截器是路由框架的核心价值之一。无论是 HMRouter 还是 ZRouter,都允许开发者在页面跳转前进行逻辑干预。

  • 全局鉴权:在跳转目标页面前,检查全局登录状态。若未登录,则中断原始跳转,重定向至登录页,并在登录成功后携带原参数继续跳转。
  • 埋点与日志:在全局拦截器中统一记录用户的页面访问轨迹(如srcName jump to targetName),无需在每个业务页面手动埋点。
import { HMInterceptor, HMInterceptorAction, IHMInterceptor, IHMInterceptorChain, HMRouterMgr } from '@hadss/hmrouter'; @HMInterceptor({ interceptorName: 'LoginCheckInterceptor' }) export class LoginCheckInterceptor implements IHMInterceptor { async intercept(chain: IHMInterceptorChain): Promise<void> { const info = chain.getRouterInfo(); const isLogin = false; // 模拟未登录状态 if (!isLogin && info.targetName === 'page/profile') { // 拦截原始跳转,重定向至登录页 info.context.getPromptAction().showToast({ message: '请先登录' }); HMRouterMgr.push({ pageUrl: 'page/login', param: { targetUrl: info.targetName }, skipAllInterceptor: true // 登录页跳转跳过拦截器,防止死循环 }); await chain.onIntercept(); // 拦截原始请求 } else { await chain.onContinue(); // 放行,继续执行跳转 } } }

四、 宿主容器与路由栈管理

  1. 路由表与名称一致性:使用pushPathByName时,传入的名称必须与配置文件(如route_map.json或注解中的pageUrl)完全一致,否则会导致跳转白屏或失败。
  2. 参数类型安全:跨页面传递复杂对象时,建议统一定义 Interface(如DetailParam)并导出,避免在多个页面中“随手拼对象”导致字段缺失或类型错误。
  3. 编译插件版本对齐:使用 HMRouter 等基于代码生成的框架时,必须确保编译插件(如@hadss/hmrouter-plugin)与核心库的版本严格一致,否则会导致编译失败或路由表生成异常。
  4. 宿主容器不可缺失:HMRouter 依赖系统的 Navigation 能力,必须在根页面(通常是@Entry组件)中包裹HMNavigationNavigation(ZRouter.getNavStack())容器,否则 push 操作会因找不到“宿主栈”而失效。
import { HMNavigation, HMDefaultGlobalAnimator } from '@hadss/hmrouter'; // 在根页面(@Entry)中必须包裹 HMNavigation 容器 @Entry @Component struct Index { build() { Column() { HMNavigation({ navigationId: 'mainNavigation', homePageUrl: 'page/home', // 首页路由地址 options: { standardAnimator: HMDefaultGlobalAnimator.STANDARD_ANIMATOR } }) } .width('100%') .height('100%'); } }

五、HMRouter 初始化与页面声明实战

场景:在应用启动时初始化路由框架,并通过注解声明式定义页面路由,实现跨模块的无缝跳转。

// 1. 在 EntryAbility 中初始化路由框架 import { HMRouterMgr } from '@hadss/hmrouter'; export default class EntryAbility extends UIAbility { onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { HMRouterMgr.init({ context: this.context }); } } // 2. 使用注解声明页面路由(无需手动包裹 NavDestination) import { HMRouter, HMRouterMgr } from '@hadss/hmrouter'; @HMRouter({ pageUrl: 'page/detail' }) @Component export struct DetailPage { // 自动获取路由传递的参数 @State param: Object | null = HMRouterMgr.getCurrentParam(); build() { Column() { Text(`详情页参数: ${JSON.stringify(this.param)}`).fontSize(18); Button('返回并携带结果').onClick(() => { // 返回上一页并传递结果 HMRouterMgr.pop({ param: { status: 'success' } }); }); } .width('100%') .height('100%') .justifyContent(FlexAlign.Center); } }

六、 全局拦截器实战:未登录自动重定向

场景:在跳转到个人中心等受保护页面时,全局拦截器自动检查登录状态。若未登录,则拦截原始请求并重定向至登录页。

import { HMRouterMgr, HMInterceptorAction, HMInterceptorInfo } from '@hadss/hmrouter'; // 定义全局登录拦截器 export class LoginGlobalInterceptor { handle(info: HMInterceptorInfo): HMInterceptorAction { const isLogin = false; // 模拟未登录状态 if (!isLogin && info.targetName === 'page/profile') { // 拦截原始跳转,重定向至登录页,并携带目标页URL以便登录后返回 HMRouterMgr.push({ pageUrl: 'page/login', param: { targetUrl: info.targetName }, skipAllInterceptor: true // 登录页跳转跳过拦截器,防止死循环 }); return HMInterceptorAction.DO_REJECT; // 拒绝原始跳转 } return HMInterceptorAction.DO_NEXT; // 放行,继续执行下一个拦截器或跳转 } }

七、跨模块服务路由:接口与实现解耦

场景:基础模块需要调用业务模块的方法(如获取用户信息),但不允许基础模块直接依赖业务模块。通过@HMService实现服务注册与发现。

// 1. 在业务模块中注册服务 import { HMService } from '@hadss/hmrouter'; export class UserService { @HMService({ serviceName: 'IUserService', singleton: true }) getUserInfo(): string { return '当前用户: HarmonyOS Dev'; } } // 2. 在基础模块中获取服务并调用(无需 import 实现类) // 通过 HMRouterMgr 获取服务实例 const userService = HMRouterMgr.getService('IUserService') as UserService; console.info(userService.getUserInfo());
http://www.jsqmd.com/news/1236223/

相关文章:

  • 5个实战技巧:掌握slam_toolbox实现企业级2D SLAM与终身建图
  • 异地上班中专党注意:档案自持多年如何激活,不耽误考编政审 - 资讯在线
  • 字体及第三方脚本速度影响:LCP超过2.5秒?修改这2个设置立竿见影
  • Jupynium.nvim 未来路线图:即将推出的功能与改进计划
  • 【JAVA毕设源码分享】基于springboot同人创作与分享平台系统的设计与实现(程序+文档+代码讲解+一条龙定制)
  • 如何用3D打印技术打造千元级六轴机械臂:Faze4开源项目完全指南
  • 3个必学技巧:精通Musicdl音乐下载的实战指南
  • YOLO11 RTSP流性能优化终极指南:从卡顿到流畅的完整方案
  • 深圳业主必看!装修避坑指南:5家零增项靠谱装修公司推荐 - GrowUME
  • 2026年邯郸靠谱装修公司哪家好?十大本土装修公司推荐指南 - 品牌智鉴榜
  • slam_toolbox深度技术解析:大规模环境下的终身建图与分布式SLAM架构揭秘
  • grunt-responsive-images核心功能解析:从基础尺寸设置到高级图片优化
  • 2026香港身份机构 TOP3测评:资质、通过率、性价比三维对比指南 - 资讯纵览
  • repo-automation-bots社区贡献指南:如何参与这个Google开源项目
  • AutoX:5大理由让你选择这款安卓自动化神器
  • libsm64声音播放机制:如何注册自定义音效回调函数
  • 【JAVA毕设源码分享】基于springboot食品仓库管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)
  • 福州本地黄金回收直营门店,每日更新大盘价公开公示 - 一日一测评
  • SKTagView与其他iOS标签库对比:为什么选择SKTagView?
  • Jellyfin/Emby用户必看:Posterizarr插件安装与媒体资产同步完整指南
  • Yuzu模拟器版本管理全攻略:如何轻松获取和选择最适合你的版本
  • VinXiangQi:你的智能象棋AI助手,让每一步棋都充满智慧
  • 高效下载Twitch视频的完整指南:命令行工具实战教程
  • 14-命令架构与注册机制
  • Sunshine游戏串流终极指南:打造家庭专属云游戏平台
  • 40个类别垃圾分类数据集深度解析:从数据标注到AI模型训练完整实战指南
  • 重庆线上回收手表套路多,线下交易避坑指南 - 每日生活报
  • FlashAttention终极指南:5步搞定高性能注意力机制编译与优化
  • 5分钟快速上手next-data-hooks:简化Next.js数据获取的完整教程
  • Android随笔-Retrofit