HarmonyOS Navigation 路由体系深度解析:NavDestination + NavPathStack
文章目录前言一、路由体系回顾1.1 三个核心组件的关系1.2 本项目路由配置二、NavPathStack 常用方法2.1 跳转方法2.2 返回方法三、页面间传参详解3.1 传递参数pushPathByName 第二个参数3.2 接收参数在目标页中四、完整实战三页面路由示例4.1 页面结构4.2 代码实现五、NavDestination 生命周期总结前言页面跳转是每个 App 的基础功能。HarmonyOS 提供了NavigationNavDestinationNavPathStack三件套来管理页面路由。本项目从MainPage跳转到GasStationPage就使用了这套路由体系。本篇详细讲解 NavPathStack 的各种方法以及如何实现参数传递、返回值获取、路由拦截等进阶功能。一、路由体系回顾1.1 三个核心组件的关系Navigation路由容器 ├── 维护一个 NavPathStack路由栈 ├── 渲染当前栈顶页面 └── NavDestination具体的子页面 ├── 通过 Builder 函数注册 └── 通过 pushPathByName 跳转到1.2 本项目路由配置路由映射自动扫描GasStationPage.ets文件顶部导出了一个Builder函数// GasStationPage.etsBuilderexportfunctionGasStationPageBuilder(){GasStationPage();}配合route_map.json或自动扫描将GasStationPage名称映射到这个 Builder 函数。跳转调用MainPage// MainPage.etsRow(){// ...}.onClick((){this.pageInfos.pushPathByName(GasStationPage,true);// ↑ 路由名称 ↑ 是否带动画})接收目标页GasStationPage// GasStationPage.etsNavDestination(){// ... 页面内容}.onReady((context:NavDestinationContext){// 获取路由栈用于在子页面内部进行路由操作this.pageInfoscontext.pathStack;})二、NavPathStack 常用方法2.1 跳转方法// 创建路由栈在 Entry 页面中constpathStack:NavPathStacknewNavPathStack();// 方式1按名称跳转pathStack.pushPathByName(DetailPage,{id:001,name:望京站});// 方式2按名称跳转带动画控制pathStack.pushPathByName(DetailPage,null,false);// false 不带动画// 方式3跳转并等待返回值async/awaitconstresultawaitpathStack.pushPathByName(SelectPage,null,true);console.log(返回值${JSON.stringify(result)});// 获取 SelectPage 的返回结果// 方式4替换当前页不入栈直接替换pathStack.replacePath({name:LoginPage,param:{}});// 方式5跳转到路由栈中已有的页面不重复入栈pathStack.moveToTop(MainPage);2.2 返回方法// 返回上一页pathStack.pop();// 返回上一页并传递结果pathStack.pop({status:success,selectedId:001});// 返回到指定路由弹出多层pathStack.popToName(MainPage);// 清空路由栈回到根页面pathStack.clear();// 获取当前栈的深度constdepthpathStack.size();// 栈中页面数量三、页面间传参详解3.1 传递参数pushPathByName 第二个参数// 跳转时传参pathStack.pushPathByName(StationDetailPage,{stationId:001,stationName:望京石化,latitude:40.0046,longitude:116.4823});3.2 接收参数在目标页中Componentstruct StationDetailPage{StatestationId:string;StatestationName:string;privatelatitude:number0;privatelongitude:number0;build(){NavDestination(){Column({space:16}){Text(ID:${this.stationId})Text(名称:${this.stationName})Text(坐标:${this.latitude},${this.longitude})}.padding(24)}.onReady((context:NavDestinationContext){// 获取路由参数constparamscontext.pathInfo.paramasRecordstring,string|number;this.stationIdparams[stationId]asstring;this.stationNameparams[stationName]asstring;this.latitudeparams[latitude]asnumber;this.longitudeparams[longitude]asnumber;}).title(this.stationName)}}四、完整实战三页面路由示例4.1 页面结构MainListPage列表页 ↓ pushPathByName(StationDetail, {id}) StationDetailPage详情页 ↓ pushPathByName(MapPage, {lat, lng}) MapPage地图页 ↓ pop({navigated: true}) StationDetailPage接收返回值 ↓ pop() MainListPage4.2 代码实现// 根容器app的最外层EntryComponentstruct AppRoot{ProvidepageInfos:NavPathStacknewNavPathStack();BuilderpageBuilder(name:string,param:Object){if(nameStationDetail){StationDetailPage()}elseif(nameMapPage){MapPage()}}build(){Navigation(this.pageInfos){MainListPage()}.navDestination(this.pageBuilder).hideNavBar(false).title(附近加油站).width(100%).height(100%)}}interfaceStationInfo{id:string;name:string;lat:number;lng:number;}interfaceMapParams{lat:number;lng:number;}// 列表页 Componentstruct MainListPage{ConsumepageInfos:NavPathStack;// 从父级 Navigation 继承路由栈privatestations:StationInfo[][{id:001,name:望京石化,lat:40.0046,lng:116.4823},{id:002,name:朝阳石油,lat:39.9219,lng:116.4386},];build(){List({space:12}){ForEach(this.stations,(station:StationInfo){ListItem(){Text(station.name).fontSize(16).padding(16).width(100%).backgroundColor(#FFFFFF).borderRadius(12).onClick((){this.pageInfos.pushPathByName(StationDetail,station);})}})}.padding(16)}}// 详情页 Componentstruct StationDetailPage{StatestationInfo:Recordstring,string|number{};pageInfos:NavPathStacknewNavPathStack();build(){NavDestination(){Column({space:16}){Text(加油站${this.stationInfo[name]asstring}).fontSize(18).fontWeight(FontWeight.Bold)Button(查看地图).onClick((){constparams:MapParams{lat:this.stationInfo[lat]asnumber,lng:this.stationInfo[lng]asnumber};this.pageInfos.pushPathByName(MapPage,params);})Button(返回列表).onClick((){this.pageInfos.pop();})}.padding(24)}.onReady((context:NavDestinationContext){this.pageInfoscontext.pathStack;this.stationInfocontext.pathInfo.paramasRecordstring,string|number;}).title(this.stationInfo[name]asstring||详情)}}// 地图页 Componentstruct MapPage{Statelat:number0;Statelng:number0;pageInfos:NavPathStacknewNavPathStack();build(){NavDestination(){Column({space:16}){Text(地图坐标${this.lat.toFixed(4)},${this.lng.toFixed(4)}).fontSize(16)Text(这里放地图组件).fontColor(#999999)Button(返回详情).onClick((){// 返回并传递结果this.pageInfos.pop({navigated:true,timestamp:Date.now()});})}.padding(24).justifyContent(FlexAlign.Center)}.onReady((context:NavDestinationContext){this.pageInfoscontext.pathStack;constparamscontext.pathInfo.paramasRecordstring,number;this.latparams[lat];this.lngparams[lng];}).title(地图视图)}}五、NavDestination 生命周期NavDestination(){// 页面内容}.onReady((context:NavDestinationContext){// ① 页面准备完成可以获取路由参数this.pageInfoscontext.pathStack;this.paramscontext.pathInfo.param;}).onWillAppear((){// ② 页面将要出现动画开始前console.log(页面将要出现);}).onAppear((){// ③ 页面已完全出现console.log(页面已出现);}).onWillDisappear((){// ④ 页面将要消失动画开始前console.log(页面将要消失);}).onDisappear((){// ⑤ 页面已消失console.log(页面已消失可以清理资源);}).onBackPressed((){// ⑥ 拦截返回键返回 true 已处理不执行默认返回if(this.hasUnsavedChanges){this.showSaveDialog();// 弹出保存对话框returntrue;// 阻止默认返回行为}returnfalse;// 允许正常返回})本项目中的生命周期// GasStationPage.etsNavDestination(){/* ... */}.onReady((context:NavDestinationContext){this.pageInfoscontext.pathStack;// 获取路由栈}).onWillAppear((){// 页面将要显示时初始化地图this.init().then((){setTimeout((){this.isShowtrue;// 500ms后显示弹窗},Constants.TIME);});})总结Navigation 路由体系通过NavPathStack管理页面栈pushPathByName跳转并传参pop返回并传递结果NavDestination的onReady回调接收参数。掌握路由栈的深度管理push/pop/popToName/clear和生命周期回调onWillAppear/onWillDisappear/onBackPressed你就能构建任意复杂的多页面应用。