摘要
原生 router 接口存在大量重复代码:页面路径硬编码、传参类型转换繁琐、返回栈管控混乱、无登录拦截、无转场动画统一配置、HSP 动态分包跳转不兼容。基于原生@ohos.router封装全局路由工具类,统一管理页面常量、普通跳转 / 替换 / 返回 / 清除栈、登录权限拦截、页面参数读写、转场动画、HSP 分包路由,大幅简化页面跳转代码,规范工程页面路径管理。API23 重构路由栈生命周期、参数序列化、跨分包页面寻址逻辑,修复页面参数丢失、返回栈堆积、HSP 页面跳转 404、路由传参对象解析失败等问题。本文提供完整可复用 RouterUtil 工具,配套首页、登录、笔记 HSP 页面实战调用,输出路由分层、权限拦截、分包跳转规范,是项目全局基础工具必备模块。
关键词
OpenHarmony;ArkTS;API23;router;路由封装;页面跳转;路由拦截;HSP 分包路由;页面传参
一、引言
1.1 路由封装开发痛点
原生 router 直接使用存在诸多工程化缺陷:
- 页面路径硬编码分散在各个页面,修改路径需要全局检索替换,极易漏改报错;
- 每次跳转重复编写转场动画、loading;
- 未做登录拦截,未登录可直接访问个人中心、笔记等私密页面;
- 页面传参读取代码重复,复杂对象参数序列化解析繁琐;
- 无法统一处理 HSP 动态分包特殊路由格式;
- 页面返回栈无管控,多次跳转后栈深度过大,连续返回卡顿。
封装统一路由工具实现:
- 全部页面路径集中常量管理,一处修改全局生效;
- 封装 push/replace/back/clearAll 路由方法,内置统一滑动转场动画;
- 增加路由前置拦截,未登录自动拦截跳转登录页;
- 统一参数存入、读取方法,自动处理普通类型与对象;
- 兼容 entry 普通页面与 HSP 动态分包页面路由格式;
- 提供清空路由栈、回到首页方法,解决返回栈堆积。
API23 router 核心升级点:
- 统一跨 HSP 分包页面路由寻址规则,标准化
hsp名/页面路径格式; - 优化路由参数缓存生命周期,页面销毁自动清理参数避免脏数据;
- 完善 RouterTransition 转场动画参数,支持自定义时长进出动画;
- 修复复杂对象参数传递丢失字段、数组解析失败问题;
- 强化路由栈销毁机制,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 路径管理规范
- 所有页面路径统一写入
PAGE_ROUTE常量,禁止页面内硬编码字符串路径; - HSP 分包名统一存入
HSP_NAME,跳转使用pushHsp专用方法; - 页面路径分层命名:pages / 模块名 / 页面名,便于维护。
5.2 登录拦截规范
- 个人中心、笔记、付费业务等私密页面跳转时传入
needLogin=true; - 首页、登录页、用户协议页面无需登录,默认 false;
- 未登录自动弹窗提示并跳转登录页,无需每个页面重复判断。
5.3 跳转方法选用规范
- 普通浏览页面(列表→详情):push,保留返回栈;
- 登录→首页、启动页→首页:replace,避免返回回到登录页;
- 退出登录、注销账号:clearAndLogin,清空全部历史栈;
- 返回首页清除中间页面:clearToIndex;
- HSP 动态分包页面:统一使用 pushHsp,拼接标准路由前缀。
5.4 页面传参规范
- 简单字符串 / 数字直接作为 params 字段;
- 对象、数组完整封装到 params 内部字段传递;
- 接收参数统一使用
RouterUtil.getParams<T>()泛型约束类型,避免 any。
5.5 转场动画规范
- 全局统一默认右滑进入动画,统一时长 350ms;
- 弹窗、共享元素页面可传入自定义 options 覆盖默认动画;
- 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、状态管理全套架构代码。