OpenHarmony 路由封装 RouterUtil 页面跳转统一管理(API Version23+)

摘要

原生 router 接口存在大量重复代码:页面路径硬编码、传参类型转换繁琐、返回栈管控混乱、无登录拦截、无转场动画统一配置、HSP 动态分包跳转不兼容。基于原生@ohos.router封装全局路由工具类,统一管理页面常量、普通跳转 / 替换 / 返回 / 清除栈、登录权限拦截、页面参数读写、转场动画、HSP 分包路由,大幅简化页面跳转代码,规范工程页面路径管理。API23 重构路由栈生命周期、参数序列化、跨分包页面寻址逻辑,修复页面参数丢失、返回栈堆积、HSP 页面跳转 404、路由传参对象解析失败等问题。本文提供完整可复用 RouterUtil 工具,配套首页、登录、笔记 HSP 页面实战调用,输出路由分层、权限拦截、分包跳转规范,是项目全局基础工具必备模块。

关键词

OpenHarmony;ArkTS;API23;router;路由封装;页面跳转;路由拦截;HSP 分包路由;页面传参

一、引言

1.1 路由封装开发痛点

原生 router 直接使用存在诸多工程化缺陷:

  1. 页面路径硬编码分散在各个页面,修改路径需要全局检索替换,极易漏改报错;
  2. 每次跳转重复编写转场动画、loading;
  3. 未做登录拦截,未登录可直接访问个人中心、笔记等私密页面;
  4. 页面传参读取代码重复,复杂对象参数序列化解析繁琐;
  5. 无法统一处理 HSP 动态分包特殊路由格式;
  6. 页面返回栈无管控,多次跳转后栈深度过大,连续返回卡顿。

封装统一路由工具实现:

  1. 全部页面路径集中常量管理,一处修改全局生效;
  2. 封装 push/replace/back/clearAll 路由方法,内置统一滑动转场动画;
  3. 增加路由前置拦截,未登录自动拦截跳转登录页;
  4. 统一参数存入、读取方法,自动处理普通类型与对象;
  5. 兼容 entry 普通页面与 HSP 动态分包页面路由格式;
  6. 提供清空路由栈、回到首页方法,解决返回栈堆积。

API23 router 核心升级点:

  1. 统一跨 HSP 分包页面路由寻址规则,标准化hsp名/页面路径格式;
  2. 优化路由参数缓存生命周期,页面销毁自动清理参数避免脏数据;
  3. 完善 RouterTransition 转场动画参数,支持自定义时长进出动画;
  4. 修复复杂对象参数传递丢失字段、数组解析失败问题;
  5. 强化路由栈销毁机制,clear 清空全部历史页面释放组件内存。

1.2 前置依赖

ets

复制代码
import router from '@ohos.router'
import AppStorage from '@ohos.arkui.state.AppStorage'
import promptAction from '@ohos.promptAction'
import { STORAGE_KEY, PAGE_ROUTE } from '../model/Constant'

二、全局路由工具封装 utils/router_util.ets

ets

复制代码
import router from '@ohos.router'
import AppStorage from '@ohos.arkui.state.AppStorage'
import promptAction from '@ohos.promptAction'
import { STORAGE_KEY, PAGE_ROUTE } from '../model/Constant'

// 转场动画默认配置
const DEFAULT_TRANSITION: router.RouterOptions = {
  transition: router.RouterTransition.SlideRight,
  duration: 350
}

class RouterUtil {
  private static instance: RouterUtil

  static getInstance(): RouterUtil {
    if (!RouterUtil.instance) {
      RouterUtil.instance = new RouterUtil()
    }
    return RouterUtil.instance
  }

  // 私有方法:登录权限拦截校验
  private checkLogin(): boolean {
    const isLogin = AppStorage.Get<boolean>(STORAGE_KEY.IS_LOGIN)
    if (!isLogin) {
      promptAction.showToast({ message: "请先登录" })
      // 跳转登录页,清除原有栈
      this.clearAndLogin()
      return false
    }
    return true
  }

  /**
   * 普通入栈跳转(保留当前页面到返回栈,可返回)
   * @param url 页面路径常量
   * @param params 传递参数对象
   * @param needLogin 是否需要登录校验
   * @param options 自定义转场动画
   */
  push(url: string, params: Object = {}, needLogin: boolean = false, options?: router.RouterOptions) {
    // 需要登录且未登录直接拦截
    if (needLogin && !this.checkLogin()) return
    router.pushUrl({ url, params }, options ?? DEFAULT_TRANSITION)
  }

  /**
   * 替换当前页面(不存入返回栈,返回不会回到上一页)
   */
  replace(url: string, params: Object = {}, needLogin: boolean = false, options?: router.RouterOptions) {
    if (needLogin && !this.checkLogin()) return
    router.replaceUrl({ url, params }, options ?? DEFAULT_TRANSITION)
  }

  /**
   * 返回上一页
   * @param delta 返回层数,默认1
   */
  back(delta: number = 1) {
    router.back(delta)
  }

  /**
   * 获取页面传递参数
   */
  getParams<T>(): T {
    return router.getParams() as T
  }

  /**
   * 清空全部路由栈,跳转首页
   */
  clearToIndex(params: Object = {}) {
    router.clear()
    router.replaceUrl({ url: PAGE_ROUTE.INDEX, params }, DEFAULT_TRANSITION)
  }

  /**
   * 清空栈并跳转登录页(退出登录专用)
   */
  clearAndLogin() {
    router.clear()
    router.replaceUrl({ url: PAGE_ROUTE.LOGIN }, DEFAULT_TRANSITION)
  }

  /**
   * HSP动态分包页面跳转专用方法
   * @param hspName HSP模块名
   * @param pagePath HSP内页面完整路径
   * @param params 传参
   */
  pushHsp(hspName: string, pagePath: string, params: Object = {}) {
    const fullUrl = `${hspName}/${pagePath}`
    router.pushUrl({ url: fullUrl, params }, DEFAULT_TRANSITION)
  }
}

export default RouterUtil.getInstance()

三、全局页面常量统一管理 model/Constant.ets

ets

复制代码
// 页面路由常量,统一管理所有页面路径
export const PAGE_ROUTE = {
  // 主entry页面
  INDEX: "pages/index/index",
  LOGIN: "pages/login/login",
  SETTING: "pages/setting/setting",
  MINE: "pages/mine/mine"
}

// HSP动态分包名常量
export const HSP_NAME = {
  NOTE: "hsp_note"
}

// AppStorage全局状态key
export const STORAGE_KEY = {
  IS_LOGIN: "isLogin",
  DARK_MODE: "darkMode",
  TOKEN: "token"
}

四、多场景业务页面实战调用

4.1 首页跳转个人中心(需要登录拦截)

ets

复制代码
import RouterUtil from '../utils/router_util'
import { PAGE_ROUTE } from '../model/Constant'

@Entry
@Component
struct Index {
  build() {
    Column() {
      Button("进入个人中心(需登录)")
        .width(300)
        .height(48)
        .onClick(() => {
          // 第三个参数true开启登录校验
          RouterUtil.push(PAGE_ROUTE.MINE, {}, true)
        })
    }
  }
}

4.2 登录页登录成功替换首页(replace 不保存返回栈)

ets

复制代码
import RouterUtil from '../utils/router_util'
import { PAGE_ROUTE } from '../model/Constant'

// 登录成功回调方法
async function loginSuccess() {
  // 替换当前登录页面,返回不会回到登录页
  RouterUtil.replace(PAGE_ROUTE.INDEX)
}

4.3 列表页跳转详情,传递对象参数

列表页传参:

ets

复制代码
// 笔记实体对象
interface NoteItem {
  id: number
  title: string
}

// 点击条目跳转详情携带数据
function jumpDetail(item: NoteItem) {
  RouterUtil.push(PAGE_ROUTE.NOTE_DETAIL, { noteInfo: item }, true)
}

详情页读取参数:

ets

复制代码
import RouterUtil from '../utils/router_util'

@Entry
@Component
struct NoteDetail {
  @State title: string = ""

  aboutToAppear() {
    type Params = { noteInfo: { id: number, title: string } }
    const params = RouterUtil.getParams<Params>()
    this.title = params.noteInfo.title
  }
}

4.4 首页跳转 HSP 笔记动态分包页面

ets

复制代码
import RouterUtil from '../utils/router_util'
import { HSP_NAME } from '../model/Constant'

Button("打开HSP笔记模块")
  .onClick(() => {
    // HSP分包跳转专用方法
    RouterUtil.pushHsp(HSP_NAME.NOTE, "src/main/ets/pages/NoteList")
  })

4.5 个人中心退出登录,清空路由栈跳转登录页

ets

复制代码
import RouterUtil from '../utils/router_util'
import AppStorage from '@ohos.arkui.state.AppStorage'

function logout() {
  // 清空全局登录状态
  AppStorage.Set("isLogin", false)
  AppStorage.Set("token", "")
  // 清空全部页面栈,跳转登录
  RouterUtil.clearAndLogin()
}

4.6 设置页返回首页,清空中间所有页面

ets

复制代码
import RouterUtil from '../utils/router_util'

Button("返回首页并清空历史页面")
  .onClick(() => RouterUtil.clearToIndex())

五、API23 路由开发编码规范

5.1 路径管理规范

  1. 所有页面路径统一写入PAGE_ROUTE常量,禁止页面内硬编码字符串路径;
  2. HSP 分包名统一存入HSP_NAME,跳转使用pushHsp专用方法;
  3. 页面路径分层命名:pages / 模块名 / 页面名,便于维护。

5.2 登录拦截规范

  1. 个人中心、笔记、付费业务等私密页面跳转时传入needLogin=true
  2. 首页、登录页、用户协议页面无需登录,默认 false;
  3. 未登录自动弹窗提示并跳转登录页,无需每个页面重复判断。

5.3 跳转方法选用规范

  1. 普通浏览页面(列表→详情):push,保留返回栈;
  2. 登录→首页、启动页→首页:replace,避免返回回到登录页;
  3. 退出登录、注销账号:clearAndLogin,清空全部历史栈;
  4. 返回首页清除中间页面:clearToIndex;
  5. HSP 动态分包页面:统一使用 pushHsp,拼接标准路由前缀。

5.4 页面传参规范

  1. 简单字符串 / 数字直接作为 params 字段;
  2. 对象、数组完整封装到 params 内部字段传递;
  3. 接收参数统一使用RouterUtil.getParams<T>()泛型约束类型,避免 any。

5.5 转场动画规范

  1. 全局统一默认右滑进入动画,统一时长 350ms;
  2. 弹窗、共享元素页面可传入自定义 options 覆盖默认动画;
  3. HSP 分包页面不建议自定义转场,避免和共享元素冲突。

六、API23 升级高频路由问题与解决方案

问题 1:未登录也能进入个人中心页面 解决:跳转 push 第三个参数传 true,开启工具内置登录拦截。

问题 2:HSP 页面跳转提示页面不存在 解决:使用 pushHsp 方法自动拼接hsp名/前缀,核对页面完整路径。

问题 3:页面传递对象参数,详情页读取字段丢失 解决:使用泛型 getParams<T>接收,避免类型丢失,API23 自动序列化完整对象。

问题 4:多次跳转后连续返回需要点很多次才能回到首页 解决:退出关键页面使用 replace,退出登录调用 clear 清空整个路由栈。

问题 5:修改页面路径后多个页面跳转 404 解决:所有路径统一在 PAGE_ROUTE 常量修改,全局一处更新。

问题 6:页面返回动画错乱、黑屏闪烁 解决:统一使用工具内置 DEFAULT_TRANSITION 标准化转场配置。

七、总结

RouterUtil 全局路由工具统一封装原生 router 全部跳转能力,解决原生路由硬编码、无登录拦截、HSP 分包不兼容、传参繁琐、路由栈堆积等工程化痛点。 工具内置登录权限拦截、标准化转场动画、普通页面 / HSP 分包双套跳转接口、参数泛型读取、路由栈清空方法,搭配全局统一页面常量管理,适配 entry 静态页面 + HSP 动态分包混合分层架构,完全兼容 API23 与 HarmonyOS NEXT,是所有鸿蒙项目必备基础底层工具,可无缝对接前文 HAR、HSP、状态管理全套架构代码。

相关推荐
春卷同学2 小时前
HarmonyOS掌上记账APP开发实践第18篇:编译时优化与 ArkTS 语法限制 — 提升应用性能的编码规范
linux·运维·ubuntu
江南风月2 小时前
WGCLOUD支持创建子账号吗
运维·zabbix·运维开发·prometheus
爸爸6192 小时前
鸿蒙应用开发实战【08】— AppStorage 全局状态与跨页面通信
ubuntu·华为·harmonyos·鸿蒙系统
ldsweet2 小时前
HarmonyOS技术精讲-剪贴板服务:进阶技巧与延迟粘贴
华为·harmonyos
一缕清烟在人间2 小时前
鸿蒙应用开发实战【27】— DatabaseService 数据库初始化
javascript·数据库·harmonyos·鸿蒙系统
拥抱太阳06163 小时前
HarmonyOS 应用开发《掌上英语》第13篇:面向对象 vs 函数式:ArkTS 中的编程范式选择
harmonyos
全堆鸿蒙3 小时前
鸿蒙应用开发实战【34】— 批量操作:batchUpdateStatus 与 deleteMany
华为·harmonyos·鸿蒙系统
subin993 小时前
圣阳蓄电池企业口碑优势与核心运营策略FAQ解析
大数据·运维·人工智能·电源·ups
贾伟康3 小时前
【安心陪诊 Agent v1.1】首页可信设计实战:HTML/CSS 状态卡与急症分流
css·html·harmonyos·ai agent·首页设计