news 2026/6/8 9:05:08

HarmonyOS Navigation 路由体系深度解析:NavDestination + NavPathStack

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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 提供了Navigation+NavDestination+NavPathStack三件套来管理页面路由。本项目从MainPage跳转到GasStationPage就使用了这套路由体系。

本篇详细讲解 NavPathStack 的各种方法,以及如何实现参数传递、返回值获取、路由拦截等进阶功能。

一、路由体系回顾

1.1 三个核心组件的关系

Navigation(路由容器) ├── 维护一个 NavPathStack(路由栈) ├── 渲染当前栈顶页面 └── NavDestination(具体的子页面) ├── 通过 @Builder 函数注册 └── 通过 pushPathByName 跳转到

1.2 本项目路由配置

路由映射(自动扫描):GasStationPage.ets文件顶部导出了一个@Builder函数:

// GasStationPage.ets@BuilderexportfunctionGasStationPageBuilder(){GasStationPage();}

配合route_map.json(或自动扫描)将'GasStationPage'名称映射到这个 Builder 函数。

跳转调用(MainPage):

// MainPage.etsRow(){// ...}.onClick(()=>{this.pageInfos.pushPathByName('GasStationPage',true);// ↑ 路由名称 ↑ 是否带动画})

接收目标页(GasStationPage):

// GasStationPage.etsNavDestination(){// ... 页面内容}.onReady((context:NavDestinationContext)=>{// 获取路由栈(用于在子页面内部进行路由操作)this.pageInfos=context.pathStack;})

二、NavPathStack 常用方法

2.1 跳转方法

// 创建路由栈(在 @Entry 页面中)constpathStack:NavPathStack=newNavPathStack();// 方式1:按名称跳转pathStack.pushPathByName('DetailPage',{id:'001',name:'望京站'});// 方式2:按名称跳转(带动画控制)pathStack.pushPathByName('DetailPage',null,false);// false = 不带动画// 方式3:跳转并等待返回值(async/await)constresult=awaitpathStack.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();// 获取当前栈的深度constdepth=pathStack.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:number=0;privatelongitude:number=0;build(){NavDestination(){Column({space:16}){Text(`ID:${this.stationId}`)Text(`名称:${this.stationName}`)Text(`坐标:${this.latitude},${this.longitude}`)}.padding(24)}.onReady((context:NavDestinationContext)=>{// 获取路由参数constparams=context.pathInfo.paramasRecord<string,string|number>;this.stationId=params['stationId']asstring;this.stationName=params['stationName']asstring;this.latitude=params['latitude']asnumber;this.longitude=params['longitude']asnumber;}).title(this.stationName)}}

四、完整实战:三页面路由示例

4.1 页面结构

MainListPage(列表页) ↓ pushPathByName('StationDetail', {id}) StationDetailPage(详情页) ↓ pushPathByName('MapPage', {lat, lng}) MapPage(地图页) ↓ pop({navigated: true}) StationDetailPage(接收返回值) ↓ pop() MainListPage

4.2 代码实现

// ====== 根容器(app的最外层)======@Entry@Componentstruct AppRoot{@ProvidepageInfos:NavPathStack=newNavPathStack();@BuilderpageBuilder(name:string,param:Object){if(name==='StationDetail'){StationDetailPage()}elseif(name==='MapPage'){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:Record<string,string|number>={};pageInfos:NavPathStack=newNavPathStack();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.pageInfos=context.pathStack;this.stationInfo=context.pathInfo.paramasRecord<string,string|number>;}).title(this.stationInfo['name']asstring||'详情')}}// ====== 地图页 ======@Componentstruct MapPage{@Statelat:number=0;@Statelng:number=0;pageInfos:NavPathStack=newNavPathStack();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.pageInfos=context.pathStack;constparams=context.pathInfo.paramasRecord<string,number>;this.lat=params['lat'];this.lng=params['lng'];}).title('地图视图')}}

五、NavDestination 生命周期

NavDestination(){// 页面内容}.onReady((context:NavDestinationContext)=>{// ① 页面准备完成,可以获取路由参数this.pageInfos=context.pathStack;this.params=context.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.pageInfos=context.pathStack;// 获取路由栈}).onWillAppear(()=>{// 页面将要显示时初始化地图this.init().then(()=>{setTimeout(()=>{this.isShow=true;// 500ms后显示弹窗},Constants.TIME);});})

总结

Navigation 路由体系通过NavPathStack管理页面栈,pushPathByName跳转并传参,pop返回并传递结果,NavDestinationonReady回调接收参数。掌握路由栈的深度管理(push/pop/popToName/clear)和生命周期回调(onWillAppear/onWillDisappear/onBackPressed),你就能构建任意复杂的多页面应用。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/8 9:05:07

CacheP2P入门指南:5分钟学会使用WebTorrent构建分布式浏览器缓存

CacheP2P入门指南&#xff1a;5分钟学会使用WebTorrent构建分布式浏览器缓存 【免费下载链接】CacheP2P "More users More capacity" 项目地址: https://gitcode.com/gh_mirrors/ca/CacheP2P 想要让你的网站内容在用户之间自动共享&#xff0c;减少服务器压力…

作者头像 李华
网站建设 2026/6/8 8:59:55

Reacto插件系统深度解析:如何扩展和自定义你的开发环境

Reacto插件系统深度解析&#xff1a;如何扩展和自定义你的开发环境 【免费下载链接】reacto A sweet IDE for React.js 项目地址: https://gitcode.com/gh_mirrors/re/reacto Reacto是一款专为React.js开发者设计的开源IDE&#xff0c;它以其强大的插件系统而闻名。本文…

作者头像 李华
网站建设 2026/6/8 8:54:15

JarkViewer内存管理策略:LRU缓存机制在图像查看器中的应用

JarkViewer内存管理策略&#xff1a;LRU缓存机制在图像查看器中的应用 【免费下载链接】jarkViewer 一款简约且飞快的看图软件&#xff0c;支持 AVIF、HEIC、JPEG-XL 和 实况照片 等超多新兴图像格式&#xff01;A minimalist and lightning-fast image viewer that supports a…

作者头像 李华
网站建设 2026/6/8 8:53:56

杰理之 切换eq死机【篇】

#if defined(EXT_HP_LP_SECTIONS) && EXT_HP_LP_SECTIONS extern const struct eq_seg_info eq_tab_normal[10EXT_HP_LP_SECTIONS]; #else extern const struct eq_seg_info eq_tab_normal[10]; #endif

作者头像 李华
网站建设 2026/6/8 8:52:12

美式期权定价MATLAB工具包:支持股息、三种差分法与热方程变换

本文还有配套的精品资源&#xff0c;点击获取 简介&#xff1a;这个MATLAB工具包专为带连续股息的美式期权定价设计&#xff0c;基于Black-Scholes偏微分方程&#xff0c;提供三种可比对的数值解法&#xff1a;原始显式有限差分、原始隐式有限差分、以及先做坐标变换&#x…

作者头像 李华