鸿蒙应用开发实战【74】— 子组件 router 导航import 对比 getUIContext本文是「号码助手全栈开发系列」第 74 篇持续更新中…开源社区https://openharmonycrossplatform.csdn.net前言在号码助手项目中页面导航路由跳转有两种实现方式import { router } from kit.ArkUI的模块导入以及this.getUIContext().getRouter()的实例获取。HomePage 等核心页面选择了 import 方式本篇深入分析两种方式的异同、选型依据和最佳实践。本文涵盖router 模块导入方式详解、getUIContext().getRouter() 实例方式详解、两种方式的对比分析、HomePage 选型决策解析、子组件路由导航模式、callback 错误处理、getUIContext 的其他能力getWindow、getDisplay 等、路由栈管理最佳实践。一、import { router } 方式1.1 模块导入这是号码助手中最常用的方式在文件顶部通过import引入router// HomePage.ets — import 方式import{router}fromkit.ArkUI;import{promptAction}fromkit.ArkUI;EntryComponentstruct HomePage{build(){Column(){// 页面内容...}}/** * 统一页面导航方法 */privatenavigate(url:string,params?:Recordstring,Object):void{router.pushUrl({url:pages/${url},params:params??{},}).then((){hilog.info(0x0000,HomePage,navigate success: %{public}s,url);}).catch((error:Error){hilog.error(0x0000,HomePage,navigate failed: %{public}s,error.message);promptAction.showToast({message:页面跳转失败:${error.message},});});}}1.2 FAB 按钮导航示例// HomePage.ets — FAB 悬浮按钮导航build(){Stack(){// 主内容区域this.MainContent()// FAB 悬浮按钮Image($r(app.media.ic_add)).width(56).height(56).position({bottom:24,right:24}).onClick((){this.showActionSheet();})}.width(100%).height(100%)}privateshowActionSheet():void{ActionSheet.show({title:选择操作,buttons:[{title:添加卡号,action:()this.navigate(AddCardPage),},{title:批量导入,action:()this.navigate(PasteImportPage),},{title:取消,action:(){},},],});}1.3 带参数导航// HomePage.ets — 统计卡片点击跳转privateonStatCardClick(status:string):void{this.navigate(StatusListPage,{status});}// 应用列表行点击privateonAppItemClick(app:AppBinding):void{this.navigate(AppDetailPage,{appId:app.id});}二、this.getUIContext().getRouter() 方式2.1 组件实例获取在自定义组件内部通过getUIContext()获取路由实例// 子组件中通过 getUIContext 导航Componentstruct AppListItem{Propapp:AppBinding|nullnull;build(){Row(){// 应用信息展示Text(this.app?.app_name??)Text(this.app?.status??)}.onClick((){this.navigateToDetail();})}privatenavigateToDetail():void{constrouterthis.getUIContext().getRouter();router.pushUrl({url:pages/AppDetailPage,params:{appId:this.app?.id??0,},}).catch((error:Error){console.error(navigate failed:,error.message);});}}2.2 在 Builder 中使用在Builder函数中也可以使用getUIContext()Componentstruct CardManagePage{BuilderCardItem(card:CardEntity){Column(){Text(card.label).fontSize(16).fontWeight(FontWeight.Bold)Text(this.formatPhone(card.phone_number)).fontSize(13).fontColor(#68708A)}.onClick((){// 在 Builder 中需要使用 getUIContextthis.getUIContext().getRouter().pushUrl({url:pages/CardDetailPage,params:{cardId:card.id},}).catch((error:Error){promptAction.showToast({message:跳转失败});});})}}三、两种方式深度对比3.1 核心特性对比特性import { router }getUIContext().getRouter()导入方式模块静态导入实例方法获取生命周期依赖无需要组件已挂载编译时检查有静态类型检查无运行时获取树摇优化支持不支持上下文绑定全局单例组件树上下文在 Builder 中使用直接使用需this.getUIContext()在非组件中使用可以用不可以用在回调中使用闭包捕获即可可能丢失this上下文3.2 为什么 HomePage 使用 import 方式HomePage 选择import { router }的核心原因因素import 方式getUIContext 方式调用频率高频多个导航点同等可用代码简洁度一行router.pushUrlthis.getUIContext().getRouter().pushUrl回调上下文无this丢失问题需注意this指向统一封装容易封装为全局工具NavigationUtil只能在组件内使用静态分析IDE 可提供导入提示无法静态分析// 结论HomePage 使用 import 封装为统一方法classNavigationUtil{staticpush(url:string,params?:Recordstring,Object):Promisevoid{returnrouter.pushUrl({url:pages/${url},params:params??{}});}}// 所有页面统一调用NavigationUtil.push(StatusListPage,{status:待换绑});3.3 何时使用 getUIContext 方式// 场景一自定义子组件中需要导航Componentexportstruct MyCustomButton{privatetargetUrl:string;build(){Button(跳转).onClick((){// 子组件中推荐使用 getUIContextthis.getUIContext().getRouter().pushUrl({url:this.targetUrl,});})}}// 场景二Builder 中需要导航BuilderfunctionGlobalActionButton(icon:Resource,url:string){Image(icon).width(48).height(48).onClick((){// Builder 函数中 this 不可用需通过参数传递})}四、getUIContext 的其他能力4.1 获取窗口信息getUIContext()不仅能获取 Router还能获取窗口、显示等信息Componentstruct CustomComponent{build(){Column(){// ...}}privategetWindowSize():void{constwindowthis.getUIContext().getWindow();// 获取窗口属性constpropertieswindow.getWindowProperties();hilog.info(0x0000,Component,window size: %{public}d x %{public}d,properties.windowRect.width,properties.windowRect.height);}privategetDisplayInfo():void{constdisplaythis.getUIContext().getDisplay();hilog.info(0x0000,Component,display dpi: %{public}d,display.densityDPI);}}4.2 getUIContext 可用方法方法返回类型用途getRouter()Router页面路由导航getWindow()Window窗口属性与操作getDisplay()Display屏幕显示信息getFont()Font字体管理getMediaQuery()MediaQuery媒体查询getFolder()Folder文件夹操作五、路由方法详解5.1 常用路由 API方法说明参数pushUrl(options)压入新页面{ url, params }replaceUrl(options)替换当前页面{ url, params }back(options?)返回上一页{ url, params? }getParams()获取当前页面参数无getState()获取路由栈状态无clear()清空路由栈无5.2 路由栈管理// 获取路由栈状态privatecheckRouteStack():void{conststaterouter.getState();hilog.info(0x0000,Router,route stack: index%{public}d, size%{public}d,state.index,state.size);}// 返回并传参privategoBackWithResult():void{router.back({url:pages/HomePage,params:{result:success},});}// 替换页面不保留返回privatereplaceToLogin():void{router.replaceUrl({url:pages/LoginPage,});}六、错误处理与最佳实践6.1 统一错误处理// common/utils/RouteUtil.ets — 统一路由管理import{router}fromkit.ArkUI;import{promptAction}fromkit.ArkUI;import{hilog}fromkit.PerformanceAnalysisKit;constTAGRouteUtil;exportclassRouteUtil{staticpush(url:string,params?:Recordstring,Object):Promisevoid{returnrouter.pushUrl({url:pages/${url},params:params??{},}).catch((error:Error){hilog.error(0x0000,TAG,pushUrl failed: url%{public}s, error%{public}s,url,error.message);promptAction.showToast({message:页面跳转失败请重试,duration:2000,});});}staticreplace(url:string,params?:Recordstring,Object):Promisevoid{returnrouter.replaceUrl({url:pages/${url},params:params??{},}).catch((error:Error){hilog.error(0x0000,TAG,replaceUrl failed: %{public}s,error.message);});}staticback(params?:Recordstring,Object):void{router.back({params:params??{}});}}6.2 子组件导航模式// 模式一回调给父组件推荐Componentstruct AppListItem{Propapp:AppBinding|nullnull;privateonItemClick?:(app:AppBinding)void;build(){Row(){Text(this.app?.app_name??)}.onClick((){if(this.onItemClickthis.app){this.onItemClick(this.app);}})}}// 父组件处理导航EntryComponentstruct AppListPage{build(){ForEach(this.apps,(app:AppBinding){AppListItem({app:app,onItemClick:(item:AppBinding){RouteUtil.push(AppDetailPage,{appId:item.id});},})})}}// 模式二子组件直接导航简单场景Componentstruct SimpleLink{privateurl:string;privateparams?:Recordstring,Object;build(){Text(查看详情).fontColor(#4F7CFF).onClick((){this.getUIContext().getRouter().pushUrl({url:this.url,params:this.params??{},});})}}小结要点import routergetUIContext.getRouter推荐场景模块导入静态 import实例方法获取工具类组件内导航直接使用this.getUIContext()子组件Builder 中直接使用需注意 this 上下文Builder统一封装容易封装不方便封装项目全局静态分析支持不支持开发体验HomePage 选型✅ 采用可选高频导航页面如果这篇文章对你有帮助欢迎点赞、收藏⭐、关注你的支持是我持续创作的动力相关资源openHarmony 跨平台社区https://openharmonycrossplatform.csdn.netHarmonyOS UI 上下文 API 文档https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-uicontext-0000001821000749HarmonyOS 路由 API 官方文档https://developer.huawei.com/consumer/cn/doc/harmonyos-references/router-0000001820880781