HarmonyOS开发 :Router 和 NavPatchStatck 如何实现跳转(传参)及页面回调

本文主要是介绍HarmonyOS开发 :Router 和 NavPatchStatck 如何实现跳转(传参)及页面回调,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

路由的选择

HarmonyOS提供两种路由实现的方式,分别是 RouterNavPatchStack。两者使用场景和特效各有优劣。

组件适用场景特点备注
Router模块间与模块内页面切换通过每个页面的url实现模块间解耦
NavPathStack模块内页面切换通过组件级路由统一路由管理
  • 什么时候使用 NavPatchStack ?

如果是单包应用开发,不使用动态包(hsp)进行拆包,只是使用静态包(har)简单的进行模块拆分,那么我推荐使用 navPatchStack

  • 什么时候使用 Router ?

如果像开发 鸿蒙元服务,对单包体积有 2M 的限制,那么我们不得不使用动态包的方式。将相对独立的功能,二级页面等拆分出去,封装成动态包,可避开 dependencies 直接依赖得引用形式。

此时使用 router 跳转 url 的方式才可跳转到动态包内非直接引用的页面

NavPatchStatck 如何跳转(传参)及页面回调

NavPathStack 是配合 Navigation 一起使用的, Navigation导航组件做统一的页面跳转管理,它提供了一系列属性方法来设置页面的标题栏、工具栏以及菜单栏的各种展示样式。

如何跳转(传参)及实现页面回调?

//第一步:定义一个用于传参和实现页面回调的模型
export interface RouterModel {params?: Object, // 要传递给跳转页面的参数popCallback?: (value: Object | undefined) => void // 用于页面回调
}
//第二步,需要在应用的根页面自行维护 navStack 实例,并传递给根节点 Navigation
@Provide('navPathStack') navPathStack: NavPathStack = new NavPathStack()Navigation(this.pageInfos) {Column() {}
}
.title('NavIndex')
.navDestination(this.PageMap)// 统一管理维护路由跳转
@BuilderPageMap(name: string, params: RouterModel) {if (name === 'pageOne') {TestNavPathPage({ // TestNavPathPage 就是要跳转的目标页面routerParams: params})} else {// 默认空页面}
}

/// 任意一个页面获取 navPathStack 调用跳转并传参
@Component
export struct RouterCallbackExample {@Consume('navPathStack') navPathStack: NavPathStack;// NavPatchStack 方式跳转并获取回调navPathStackJump() {const routerParams: RouterModel = {params: '我是入参 123', //传递到跳转页面的入参popCallback: (callbackValue) => {// 这里拿到回调结果,注意要判断 callbackValue !== undefine// 这里拿到下面目标页面回传的结果 ‘我是回调的结果 345’}}this.navPathStack.pushPathByName('pageOne', routerParams) // 'pageOne' 对应上面 'PageMap' 方法内定义的路径名称常量}build() {Button('跳转').onClick(() => {this.navPathStackJump()})}
}

/// 目标页面接收入参、并返回页面回调
@Component
export struct TestNavPathPage {@Consume('navPathStack') navPathStack: NavPathStack;routerParams?: RouterModel@State receiveParams: string = ''aboutToAppear(): void {// 接收入参,这里拿到上面传入的 ‘我是入参 123’let receiveParams = this.routerParams!.params}build() {NavDestination() {Button('关闭页面并回调结果').onClick(() => {if (this.routerParams?.popCallback !== undefined) {this.routerParams.popCallback('我是回调的结果 345 ')}this.navPathStack.pop()})}.title('跳转目标页')}
}

Router 如何跳转(传参)及页面回调

Router 跳转可支持跳转本包内页面以及动态包或者拆包内的页面,

  • url 的定义举例如下:
1. 本地包内,或者直接依赖的静态包内页面,url 定义为 : pages/Page1
2. 分包内的页面,url 定义为 :@bundle:com.rex.harmony.atomic.service/featureName/ets/pages/Page2// com.rex.harmony.atomic.service 是我的应用包名
// featureName 是跳转页面所在的模块名称,对应 module.json5 里面额 name
// ets/pages/Page2 为目标页面在模块内的页面路径,对应 main_pages.json 内的页面路径
  • url 跳转
router.pushUrl({ url: '', params: Object })
  • 注意: 使用 router + url 进行跳转的目标页面必须使用 @Entry 修饰,且在main_pages.json 文件内填写对应路径

重点:截止 API11 版本,router 支持传递的 params 传参,不是引用传递,所以在动态包内实际获取到的不是同一个对象,为了实现页面回调,router 我们需要做如下封装:

  • 如何跳转(传参)及实现页面回调?抛砖引玉 ---
  1. 在公共的har包内定义 Router 管理类 FastRouter

(在下文扩展中解释单例为什么这么实现)

import { RouterModel } from './model/RouterModel'
import { router } from '@kit.ArkUI'/// 基于 router 库封装,为了实现页面回调
export class FastRouter {public readonly routerStack: RouterModel[] = []/// 跨 hsp 使用这种方式实现单例public static instance(): FastRouter {const storageKey = 'REX_FAST_ROUTER'if (!AppStorage.has(storageKey)) {AppStorage.setOrCreate(storageKey, new FastRouter())}return AppStorage.get<FastRouter>(storageKey)!}/// 获取路由传递的入参public static get getRouterCurrentParams(): RouterModel | undefined {const stack = FastRouter.instance().routerStackif (stack.length === 0) {return undefined}return stack[stack.length - 1]}/// push 页面public static async push(route: RouterModel): Promise<void> {try {await router.pushUrl({ url: route.url, params: route.params })FastRouter.instance().routerStack.push(route)} catch (_) {console.log('>>>>')}}/// replace 页面public static async replace(route: RouterModel): Promise<void> {try {await router.replaceUrl({ url: route.url, params: route.params })const instance = FastRouter.instance()const list = instance.routerStackif (list.length > 0) {instance.routerStack.splice(instance.routerStack.length - 1, 1, route)}} catch (_) {// 暂无处理}}/// 退出栈顶页面public static async pop(animated?: boolean): Promise<void> {router.back()const routerStack = FastRouter.instance().routerStackrouterStack.pop()}
}
  1. 任一页面使用 FastRouter 进行 url 跳转
// 跳转到 hsp 包(feature_hsp_page)内的 TestHspHomePage 页面
const routerParams: RouterModel = {url: '@bundle:com.rex.harmony.atomic.service/feature_hsp_page/ets/pages/TestHspHomePage',params: '我是入参 1488',popCallback: (callbackValue) => {if (callbackValue !== undefined) {//这里获取跳转页的回调数据//接收到下文中目标页面的回调结果:‘我是回调的结果 6100 ’}}
}
FastRouter.push(routerParams)
  1. 在目标页面内接收入参并回调结果
@Entry
@Component
struct Index {routerParams?: RouterModelaboutToAppear(): void {this.routerParams = FastRouter.getRouterCurrentParams as RouterModellet receiveParams = this.routerParams.params //这里接收入参,也就是上面传递的 ‘我是入参 1488’}build() {Button('关闭页面并回调结果').onClick(() => {if (this.routerParams?.popCallback !== undefined) {this.routerParams.popCallback('我是回调的结果 6100 ')}FastRouter.pop()})}
}

总结

NavPatchStackRouter 两种路由方式各有优劣,NavPatchStack 方便统一管理,Router 方便解耦,两者没有任何关联,可以一起使用,也可以单独使用。

扩展:动态包、静态包的使用差异

说到动态包(HAR)和静态包(HSP),这里扩展一下两者的区别。

静态包的 module.json5 文件,type 标识为 har

{"module": {"name": "静态包模块名称","type": "har","deviceTypes": ["default","tablet"]}
}

静态包的 module.json5 文件,type 标识为 shared

{"module": {"name": "动态包模块名称","type": "shared","description": "$string:shared_desc","deviceTypes": ["phone","tablet"],"deliveryWithInstall": true,"installationFree": true,"pages": "$profile:main_pages"}
}

动态包和静态包都可以被直接引用,在 oh-package.json5

{...省略"dependencies": {"@rex/任意名称": "file:../../base/静态包模块名称","@rex/任意名称": "file:../../base/动态包模块名称"}
}

重点:

  • 动态包可以不直接依赖( 例如:使用 preload ),跳转动态包内的页面可以通过 router 拼接 url 进行跳转
  • har 中的代码和资源跟随使用方编译,如果有多个使用方,存在多个 hap,也包括使用了 hsp 的场景。该 har 的编译产物中会存在多份相同拷贝。

存在两种情况,如果harA和harB都依赖harC,单个hap依赖harA、harB,那么只会存在一份harA、harB、harC;如果harA和harB都依赖harC,有两个hap,hapA依赖harA,hapB依赖harB,那么最终会存在一份harA、harB,两份harC;

  • hsp 中的代码和资源可以独立编译,运行时在一个进程中代码也只会存在一份

举个例子:

  • 如果应用内没有使用动态包,或者把单例的封装放在动态包里被其他包(静态包或动态包)直接依赖,我们的单例可以这么写:
    class SimgleProvider {private static _instance?: SimgleProviderpublic static instance(): SimgleProvider {if (!SimgleProvider._instance) {SimgleProvider._instance = new SimgleProvider()}return SimgleProvider._instance}}
  • 在应用的任意一处获取这个单例都是同一个对象

  • 但如果单例封装放在 har 包内,该 har 包被其他包(静态包和动态包)依赖引用。仍然使用上述代码实现单例,我们在 entry 或者 被 entry 直接依赖的 har 中获取到的 SimgleProvider 单例 和在 hsp 包内获取到的 SimgleProvider 单例 不是指向同一份内存,它会被拷贝两份。

可以简单的总结为:一个应用内,同一个 har 包,如果同时被 har (或者entry)和 hsp 依赖引用,会被拷贝两份。

  • 如果需要整个应用内,包括 entry、har、hsp 都指向的是同一个单例对象,要么把这个单例封装放在 hsp 内,如果单例封装放在 har 内,需要把上面的单例实现代码改成如下:
class SimgleProvider {private static _instance?: SimgleProviderpublic static instance(): FastRouter {const storageKey = 'SimgleProvider'if (!AppStorage.has(storageKey)) {AppStorage.setOrCreate(storageKey, new SimgleProvider())}return AppStorage.get<SimgleProvider>(storageKey)!}
}
  • 借助AppStorage,实现全应用单例


最后

有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)资料用来跟着学习是非常有必要的。 

鸿蒙HarmonyOS Next全套学习资料←点击领取!(安全链接,放心点击

这份鸿蒙(HarmonyOS NEXT)资料包含了鸿蒙开发必掌握的核心知识要点,内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。

希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!

鸿蒙(HarmonyOS NEXT)最新学习路线

有了路线图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)与鸿蒙(OpenHarmony )开发入门教学视频,内容包含:ArkTS、ArkUI、Web开发、应用模型、资源分类…等知识点。

获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料

HarmonyOS Next 最新全套视频教程

《鸿蒙 (OpenHarmony)开发基础到实战手册》

OpenHarmony北向、南向开发环境搭建

《鸿蒙开发基础》

  • ArkTS语言
  • 安装DevEco Studio
  • 运用你的第一个ArkTS应用
  • ArkUI声明式UI开发
  • .……

《鸿蒙开发进阶》

  • Stage模型入门
  • 网络管理
  • 数据管理
  • 电话服务
  • 分布式应用开发
  • 通知与窗口管理
  • 多媒体技术
  • 安全技能
  • 任务管理
  • WebGL
  • 国际化开发
  • 应用测试
  • DFX面向未来设计
  • 鸿蒙系统移植和裁剪定制
  • ……

《鸿蒙进阶实战》

  • ArkTS实践
  • UIAbility应用
  • 网络案例
  • ……

大厂面试必问面试题

鸿蒙南向开发技术

鸿蒙APP开发必备

鸿蒙生态应用开发白皮书V2.0PDF


获取以上完整鸿蒙HarmonyOS学习资料,请点击→

总结
总的来说,华为鸿蒙不再兼容安卓,对中年程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,他们才能在这个变革的时代中立于不败之地。 

这篇关于HarmonyOS开发 :Router 和 NavPatchStatck 如何实现跳转(传参)及页面回调的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1075248

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

Hadoop企业开发案例调优场景

需求 (1)需求:从1G数据中,统计每个单词出现次数。服务器3台,每台配置4G内存,4核CPU,4线程。 (2)需求分析: 1G / 128m = 8个MapTask;1个ReduceTask;1个mrAppMaster 平均每个节点运行10个 / 3台 ≈ 3个任务(4    3    3) HDFS参数调优 (1)修改:hadoop-env.sh export HDFS_NAMENOD

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

如何在页面调用utility bar并传递参数至lwc组件

1.在app的utility item中添加lwc组件: 2.调用utility bar api的方式有两种: 方法一,通过lwc调用: import {LightningElement,api ,wire } from 'lwc';import { publish, MessageContext } from 'lightning/messageService';import Ca

活用c4d官方开发文档查询代码

当你问AI助手比如豆包,如何用python禁止掉xpresso标签时候,它会提示到 这时候要用到两个东西。https://developers.maxon.net/论坛搜索和开发文档 比如这里我就在官方找到正确的id描述 然后我就把参数标签换过来