鸿蒙多功能工具箱开发实战(四)-路由导航与页面跳转
前言
路由导航是移动应用开发的核心功能之一。本文将详细讲解HarmonyOS中的路由机制,包括页面注册、路由跳转、参数传递、返回处理等核心功能。
一、HarmonyOS路由机制概述
1.1 路由配置文件
HarmonyOS使用main_pages.json配置页面路由:
{"src":["pages/Index","pages/calculator/RelativeCalculator","pages/calculator/DateCalculator","pages/calendar/LunarCalendar"]}重要规则:
- 所有页面必须在
src数组中注册 - 路径相对于
entry/src/main/ets/ - 不需要
.ets后缀
1.2 路由API
HarmonyOS提供@ohos.router模块处理路由:
importrouterfrom'@ohos.router'// 页面跳转router.pushUrl({url:'pages/Detail'})// 带参数跳转router.pushUrl({url:'pages/Detail',params:{id:123,name:'test'}})// 返回上一页router.back()// 返回并传参router.back({params:{result:'success'}})// 替换当前页面router.replaceUrl({url:'pages/Login'})// 清空路由栈并跳转router.clear()router.pushUrl({url:'pages/Index'})二、页面注册实践
2.1 创建新页面
创建entry/src/main/ets/pages/calculator/RelativeCalculator.ets:
importrouterfrom'@ohos.router'@Entry@Componentstruct RelativeCalculator{build(){Column(){// 标题栏Row(){Text('←').fontSize(24).onClick(()=>{router.back()})Text('亲戚称呼计算器').fontSize(18).fontWeight(FontWeight.Bold).layoutWeight(1).textAlign(TextAlign.Center)Text(' ')// 占位.fontSize(24)}.width('100%').height(56).padding({left:16,right:16}).justifyContent(FlexAlign.SpaceBetween)// 内容区域Column(){Text('计算功能开发中...').fontSize(16).fontColor('#999999')}.layoutWeight(1).justifyContent(FlexAlign.Center)}.width('100%').height('100%')}}图 1 计算工具页面
2.2 注册页面路由
在entry/src/main/resources/base/profile/main_pages.json中添加:
{"src":["pages/Index","pages/calculator/RelativeCalculator"]}三、路由跳转实现
3.1 基本跳转
importrouterfrom'@ohos.router'// 在工具卡片点击时跳转ToolCard({name:'亲戚称呼计算器',icon:'👨👩👧👦',description:'计算亲戚关系的称呼',color:'#4A90E2',onCardClick:()=>{router.pushUrl({url:'pages/calculator/RelativeCalculator'})}})3.2 带参数跳转
// 跳转并传递参数router.pushUrl({url:'pages/calculator/DateCalculator',params:{mode:'range',// 计算模式defaultDate:'2024-01-01'}})// 目标页面接收参数@Entry@Componentstruct DateCalculator{// 获取路由参数privateparams=router.getParams()asRecord<string,Object>privatemode:string=this.params?.modeasstring||'single'privatedefaultDate:string=this.params?.defaultDateasstring||''build(){Column(){Text(`模式:${this.mode}`)Text(`默认日期:${this.defaultDate}`)}}}3.3 路由模式
// Standard模式(默认):新页面入栈router.pushUrl({url:'pages/Detail',mode:router.RouterMode.Standard})// Single模式:如果页面已存在,移到栈顶router.pushUrl({url:'pages/Index',mode:router.RouterMode.Single})四、页面返回处理
4.1 基本返回
// 返回上一页router.back()// 返回到指定页面router.back({url:'pages/Index'})4.2 返回传参
// 详情页返回时传参@Entry@Componentstruct DetailPage{build(){Column(){Button('确认选择').onClick(()=>{router.back({params:{selectedValue:'选项A',selectedId:1}})})}}}// 上级页面接收返回参数@Entry@Componentstruct ListPage{// 监听页面显示aboutToAppear(){// 获取返回参数constparams=router.getParams()if(params?.selectedValue){console.log('用户选择:',params.selectedValue)}}}4.3 使用onBackPressed拦截返回
@Entry@Componentstruct EditorPage{@StatehasUnsavedChanges:boolean=falsebuild(){Column(){// 编辑内容...}}// 拦截返回事件onBackPress():boolean{if(this.hasUnsavedChanges){AlertDialog.show({title:'提示',message:'有未保存的更改,确定要离开吗?',primaryButton:{value:'取消',action:()=>{}},secondaryButton:{value:'确定',action:()=>{router.back()}}})returntrue// 拦截返回}returnfalse// 不拦截}}五、路由栈管理
5.1 获取路由栈信息
importrouterfrom'@ohos.router'// 获取当前路由栈长度letstackLength=router.getLength()console.log('路由栈长度:',stackLength)// 获取路由状态letstate=router.getState()console.log('当前页面:',state.name)console.log('页面路径:',state.path)5.2 替换页面
// 替换当前页面(不会增加路由栈)router.replaceUrl({url:'pages/Login'})// 使用场景:登录成功后跳转主页// 此时用户按返回键不会回到登录页5.3 清空路由栈
// 清空所有页面router.clear()// 常用于退出登录functionlogout(){// 清除用户数据clearUserData()// 清空路由栈并跳转登录页router.clear()router.replaceUrl({url:'pages/Login'})}六、实际应用示例
6.1 通用标题栏组件
创建components/TitleBar.ets:
importrouterfrom'@ohos.router'/** * 通用标题栏组件 */@Componentexportstruct TitleBar{@Proptitle:string=''@PropshowBack:boolean=trueonBackClick?:()=>voidbuild(){Row(){// 返回按钮if(this.showBack){Text('←').fontSize(24).onClick(()=>{if(this.onBackClick){this.onBackClick()}else{router.back()}})}else{Text('')// 占位.width(24)}// 标题Text(this.title).fontSize(18).fontWeight(FontWeight.Bold).layoutWeight(1).textAlign(TextAlign.Center)// 右侧占位Text('').width(24)}.width('100%').height(56).padding({left:16,right:16}).justifyContent(FlexAlign.SpaceBetween).backgroundColor('#FFFFFF').shadow({radius:2,color:'#1A000000',offsetY:1})}}6.2 使用标题栏组件
import{TitleBar}from'../components/TitleBar'@Entry@Componentstruct RelativeCalculator{build(){Column(){// 标题栏TitleBar({title:'亲戚称呼计算器'})// 内容Column(){// 页面内容...}.layoutWeight(1)}.width('100%').height('100%')}}6.3 路由工具类
创建common/RouterUtils.ets:
importrouterfrom'@ohos.router'/** * 路由工具类 */exportclassRouterUtils{// 页面路径常量staticreadonlyPAGES={INDEX:'pages/Index',RELATIVE_CALCULATOR:'pages/calculator/RelativeCalculator',DATE_CALCULATOR:'pages/calculator/DateCalculator',LUNAR_CALENDAR:'pages/calendar/LunarCalendar'}/** * 跳转到指定页面 */staticpush(url:string,params?:Record<string,Object>):void{router.pushUrl({url:url,params:params||{}}).then(()=>{console.log('路由跳转成功:',url)}).catch((err:Error)=>{console.error('路由跳转失败:',err.message)})}/** * 替换当前页面 */staticreplace(url:string,params?:Record<string,Object>):void{router.replaceUrl({url:url,params:params||{}})}/** * 返回上一页 */staticback(params?:Record<string,Object>):void{if(params){router.back({params:params})}else{router.back()}}/** * 获取路由参数 */staticgetParams<T>():T|null{constparams=router.getParams()returnparams?(paramsasT):null}/** * 判断是否可以返回 */staticcanGoBack():boolean{returnrouter.getLength()>1}}6.4 使用路由工具类
import{RouterUtils}from'../common/RouterUtils'// 跳转RouterUtils.push(RouterUtils.PAGES.RELATIVE_CALCULATOR,{mode:'edit'})// 返回RouterUtils.back({result:'success'})// 获取参数interfaceDateParams{mode:stringdefaultDate:string}constparams=RouterUtils.getParams<DateParams>()七、路由动画
7.1 页面转场动画
// 在页面组件中定义转场动画@Entry@Componentstruct DetailPage{// 页面入场动画pageTransition(){PageTransitionEnter({duration:300}).slide(SlideEffect.Right)PageTransitionExit({duration:300}).slide(SlideEffect.Left)}build(){Column(){// 页面内容}}}7.2 共享元素转场
// 列表页@Entry@Componentstruct ListPage{build(){Column(){Image($r('app.media.icon')).width(100).height(100).sharedTransition('shared_image',{duration:300}).onClick(()=>{router.pushUrl({url:'pages/Detail'})})}}}// 详情页@Entry@Componentstruct DetailPage{build(){Column(){Image($r('app.media.icon')).width(300).height(300).sharedTransition('shared_image',{duration:300})}}}八、小结
本文详细讲解了HarmonyOS路由导航的实现,核心要点:
- ✅ main_pages.json 配置页面路由
- ✅ router.pushUrl() 页面跳转
- ✅ router.getParams() 获取路由参数
- ✅ router.back() 页面返回
- ✅ onBackPress() 拦截返回事件
- ✅ router.replaceUrl() 替换页面
- ✅ 路由工具类封装
下一篇文章将讲解主题配色与全局样式管理。
系列文章导航:
下期预告:鸿蒙多功能工具箱开发实战(五)-主题配色与全局样式管理