HarmonyOs应用《日记本》开发第19篇 - 页面路由与导航机制
本篇深入探讨鸿蒙 ArkUI 中的页面路由系统分析日记应用中三个页面之间的导航关系和参数传递机制。一、路由概述在鸿蒙 ArkUI 中页面路由通过ohos.router模块实现。日记应用包含三个页面它们之间形成了清晰的导航关系┌──────────────┐ │ Index │ │ (日记列表) │ └──────┬───────┘ │ pushUrl ┌────┴────┐ pushUrl ▼ ▼ ┌────────────┐ ┌──────────────┐ │ DiaryEdit │ │ DiaryDetail │ │ (编辑/新建) │ │ (详情查看) │ └──────┬─────┘ └──────┬───────┘ │ │ │ pushUrl │ └───────────────┘二、路由配置2.1 页面注册在main_pages.json中注册所有页面{src:[pages/Index,pages/DiaryEdit,pages/DiaryDetail]}配置说明src数组列出所有页面路径第一个页面pages/Index是应用的入口页面路径相对于src/main/ets/目录2.2 页面文件位置entry/src/main/ets/ ├── pages/ │ ├── Index.ets # 日记列表页 │ ├── DiaryEdit.ets # 日记编辑页 │ └── DiaryDetail.ets # 日记详情页三、路由跳转方式3.1 pushUrl — 压栈跳转importrouterfromohos.router// 跳转到编辑页新建模式router.pushUrl({url:pages/DiaryEdit,params:{mode:create}})// 跳转到详情页router.pushUrl({url:pages/DiaryDetail,params:{id:diary.id}})pushUrl 特点将目标页面压入路由栈当前页面保留在栈底目标页面可以通过router.back()返回当前页面适合层级导航列表 → 详情 → 编辑3.2 replaceUrl — 替换跳转router.replaceUrl({url:pages/Index,params:{}})replaceUrl 特点用目标页面替换当前页面当前页面出栈无法通过router.back()返回当前页面适合登录后跳转主页等场景3.3 back — 返回上一页// 返回上一页router.back()// 返回指定页面router.back({url:pages/Index})3.4 clear — 清空路由栈router.clear()清空所有页面通常在退出应用或切换用户时使用。四、参数传递4.1 发送参数// 发送简单参数router.pushUrl({url:pages/DiaryDetail,params:{id:abc123}})// 发送复杂对象router.pushUrl({url:pages/DiaryEdit,params:{mode:edit,id:abc123,title:日记标题,content:日记内容}})4.2 接收参数aboutToAppear(){constparamsrouter.getParams()asRecordstring,stringif(params){constmodeparams.mode// edit 或 createconstidparams.id// 日记IDconsttitleparams.title// 日记标题}}参数接收注意事项router.getParams()返回Object类型需要类型断言在aboutToAppear生命周期中获取参数需要进行空值检查防止参数缺失导致崩溃4.3 参数传递的完整示例Index 页面跳转到 Detail// Index.etsprivategoToDetail(diaryId:string){router.pushUrl({url:pages/DiaryDetail,params:{id:diaryId}})}Detail 页面接收参数// DiaryDetail.etsaboutToAppear(){constparamsrouter.getParams()asRecordstring,stringif(paramsparams.id){this.diaryIdparams.idthis.loadDiaryDetail(params.id)}}Detail 页面跳转到 Edit// DiaryDetail.etsprivategoToEdit(){router.pushUrl({url:pages/DiaryEdit,params:{mode:edit,id:this.diaryId}})}Edit 页面接收参数// DiaryEdit.etsaboutToAppear(){constparamsrouter.getParams()asRecordstring,stringif(paramsparams.modeedit){this.isEditModetruethis.editIdparams.idthis.loadDiary(params.id)}}五、路由动画5.1 默认动画鸿蒙默认提供页面切换动画push从右向左滑入back从左向右滑出5.2 自定义动画router.pushUrl({url:pages/DiaryDetail,params:{id:diaryId},animations:{duration:300,curve:Curve.EaseInOut,direction:AnimationDirection.RightToLeft}})六、路由模式6.1 Standard默认router.pushUrl({url:pages/DiaryDetail,params:{id:diaryId}},router.RouterMode.Standard)每次跳转都创建新页面实例路由栈可能出现多个相同页面。6.2 Singlerouter.pushUrl({url:pages/DiaryDetail,params:{id:diaryId}},router.RouterMode.Single)如果路由栈中已有该页面将其上方的页面全部出栈复用该页面。七、路由栈管理7.1 路由栈结构初始状态: ┌──────────┐ │ Index │ ← 栈底 └──────────┘ 跳转到 Detail: ┌──────────┐ │ Detail │ ← 栈顶 ├──────────┤ │ Index │ ← 栈底 └──────────┘ 跳转到 Edit: ┌──────────┐ │ Edit │ ← 栈顶 ├──────────┤ │ Detail │ ├──────────┤ │ Index │ ← 栈底 └──────────┘ back 返回 Detail: ┌──────────┐ │ Detail │ ← 栈顶 ├──────────┤ │ Index │ ← 栈底 └──────────┘7.2 获取路由栈信息conststackSizerouter.getLength()conststackrouter.getState()console.log(当前路由栈大小:${stackSize})console.log(当前页面:${stack.name})八、路由返回携带参数8.1 通过全局状态// 编辑页面保存成功后设置全局状态AppStorage.Set(diaryUpdated,true)router.back()// 列表页面检查onPageShow(){constupdatedAppStorage.Getboolean(diaryUpdated)if(updated){this.loadDiaries()AppStorage.Set(diaryUpdated,false)}}8.2 通过 router.back params// 编辑页面router.back({url:pages/Index})// 列表页面在 onPageShow 中刷新onPageShow(){this.loadDiaries()}九、路由守卫与拦截虽然鸿蒙没有直接的路由守卫 API但可以通过封装路由方法实现拦截exportclassRouterUtil{staticpushUrl(url:string,params?:Recordstring,string){// 前置检查if(!this.checkPermission(url)){promptAction.showToast({message:无访问权限})return}router.pushUrl({url,params})}staticcheckPermission(url:string):boolean{// 权限检查逻辑returntrue}}十、总结鸿蒙路由系统的核心要点页面注册在main_pages.json中声明所有页面跳转方式pushUrl压栈、replaceUrl替换、back返回参数传递通过params传递通过router.getParams()接收路由模式Standard多实例和Single单例栈管理理解路由栈结构合理使用back和clear页面刷新通过onPageShow生命周期实现返回后刷新日记应用的路由设计简洁清晰列表 → 详情 → 编辑的三层导航是移动应用的经典模式。