HarmonyOS - Hyperlink组件和Navigator组件

幽沉谢世事,俯默窥唐虞。这篇文章主要讲述HarmonyOS - Hyperlink组件和Navigator组件相关的知识,希望能为你提供帮助。
本节讲解ArkUI eTS中实现页面跳转的三个方案。包括:使用Hyperlink组件打开浏览器跳转到第三方网页、使用Navigator组件跳转到App内的其它页面和使用页面路由接口router。对于目前Hyperlink组件Beta版存在的问题,给出了使用建议。
3.2.1 Hyperlink组件做B/S架构开发的同学,应该很熟悉超级链接组件“a”,通常,链接到另一个网页,写法如下:

< a rel="nofollow" href="http://www.baidu.com" title="百度" />

而在ArkUI eTS官方提供的组件中有一个和它对标的组件Hyperlink。该组件的接口写法为:
Hyperlink(address: string, content?: string)

其中接口参数" address" 对标" href" ,可选参数content对标" title" 。
示例代码如下:
/** * 接口:Hyperlink(address: string, content?: string) *address: string hyperlink组件跳转的网页。 *content: string hyperlink组件中超链接显示文本。 */ Hyperlink(https://ost.51cto.com/person/posts/15589203, 鸿蒙开发之南拳北腿) Image($r("app.media.cover")) .width("100%") .aspectRatio(1.5) .borderRadius($r("app.float.radius_L"))

本地预览器只能查看界面效果,无法跳转网页,所以建议在远程模拟器测试,效果如下:
HarmonyOS - Hyperlink组件和Navigator组件

文章图片

我们发现,接口参数“content”的文本“鸿蒙开发之南拳北腿”是没有显示的,点击图片后,打开浏览器,进入了参数“address”指向的网页。
在上述示范代码中,我放了一个子组件Image。但是,如果我再放入一个子组件呢?说干就干,我在Image组件后面放入一行代码:
Text(鸿蒙开发ArkUI最佳实践)

神奇的一幕发生了:在本地预览器和远程模拟器中发现,接口参数“content”的文本居然出现了!
HarmonyOS - Hyperlink组件和Navigator组件

文章图片

让人不能接受的是,这个文本字号大小不可控制,文字颜色也不可控制,在深色模式下直接就看不到了。当然,目前Hyperlink组件还处于Beta版阶段,有点小瑕疵,也是可以理解的,希望华为的同学能在Release版时优化下这个问题。
“问题”还没有完。我们给新增加的Text组件加入一点样式,代码如下:
Text(鸿蒙开发ArkUI最佳实践) .fontColor($r("app.color.fgLevel1")) .fontSize($r("app.float.fontSizeH8")) .fontWeight(Number($r("app.float.fontWeightH8")))

我们对比下浅色模式和深色模式下的效果:
HarmonyOS - Hyperlink组件和Navigator组件

文章图片

原本适配深色模式的文字,在深色模式下不再显示白色文字了!我猜,这与Hyperlink组件的color属性有关。
官方文档中对color属性的描述是: 当子组件中有文本和图片时,设置文本和图片的颜色。
可能即使未设置color属性,Hyperlink组件的color属性默认值也会作用于其子组件。那么,如何破局?代码修改如下:
Hyperlink(https://ost.51cto.com/person/posts/15589203, 鸿蒙开发之南拳北腿)// Hyperlink接口 Image($r("app.media.cover")) .width("100%") .aspectRatio(1.5) .borderRadius($r("app.float.radius_L")) Text(鸿蒙开发ArkUI最佳实践) .fontSize($r("app.float.fontSizeH8")) .fontWeight(Number($r("app.float.fontWeightH8"))) .color($r("app.color.fgLevel1")) //

效果如下:
HarmonyOS - Hyperlink组件和Navigator组件

文章图片

" app.color.fgLevel1" 这个资源颜色在浅色模式下显示为黑色,在深色模式下显示为白色。现在文字显示合理了,但图片被影响了。
对于Hyperlink组件的使用,我的建议是:
不要设置接口参数“content”;
同时,在其容器中只放一个子组件,以免互相影响;
最后,文本链接的颜色,需要通过Hyperlink的color属性设置。
上述代码改造如下:
/** * 接口:Hyperlink(address: string, content?: string) *address: string hyperlink组件跳转的网页。 *content: string hyperlink组件中超链接显示文本。 */ Hyperlink(https://ost.51cto.com/person/posts/15589203)// Hyperlink接口 Image($r("app.media.cover")) .width("100%") .aspectRatio(1.5) .borderRadius($r("app.float.radius_L"))/** * 属性:color:color 当子组件中有文本和图片时,设置文本和图片的颜色。 */ Hyperlink(https://ost.51cto.com/person/posts/15589203) Text(鸿蒙开发ArkUI最佳实践) .fontSize($r("app.float.fontSizeH8")) .fontWeight(Number($r("app.float.fontWeightH8"))) .decoration( type: TextDecorationType.Underline ) .color($r("app.color.info")) // 属性:color

浅色模式和深色模式下的效果如下:
HarmonyOS - Hyperlink组件和Navigator组件

文章图片

本小节源码位于/pages/HyperlinkSample.ets。
3.2.2 Navigator组件Navigator组件用于跳转到App内的其它页面。我们在“3.1.2 Span组件”这一小节的“1.建立页面导航”中初步使用该组件实现了首页和各个组件演示页之间互相跳转。接下来,我们正式学习这个组件的接口和属性。
新建一个NavigatorSample.ets页面,初始代码如下:
/** * 路由容器组件(Navigator):提供路由跳转能力,可以包含子组件。 */ @Entry @Component struct NavigatorSample build() Column(space:8) // 返回首页 Row(space:8) Image($r("app.media.ic_back")).width(24).height(24)Navigator( target: pages/index, type: NavigationType.Back ) Text(返回) .fontColor($r("app.color.fgLevel1")) .fontSize($r("app.float.fontSizeH8")) .fontWeight(Number($r("app.float.fontWeightH8")))/** * 接口:Navigator(value?: target: string, type?: NavigationType) *target:string 指定跳转目标页面的路径。 *type:NavigationType 默认值Push 指定路由方式。 *NavigationType.Push 跳转到应用内的指定页面。 *NavigationType.Replace 用应用内的某个页面替换当前页面,并销毁被替换的页面。 *NavigationType.Back 返回上一页面或指定的页面。 */ Navigator( target: pages/HyperlinkSample, type: NavigationType.Replace ) Text(用Hyperlink页面替换当前页面) .fontColor($r("app.color.info")) .fontSize($r("app.float.fontSizeH8")) .fontWeight(Number($r("app.float.fontWeightH8"))) .decoration( type: TextDecorationType.Underline, color: $r("app.color.info") ).width(100%).height(100%).backgroundColor($r("app.color.appBg")) // App背景颜色 .padding(top: $r("app.float.spaceTop"), bottom:$r("app.float.spaceBottom"), left:$r("app.float.spaceLeft"), right: $r("app.float.spaceRight")) // 屏幕边缘间隔 .alignItems(HorizontalAlign.Start)

在上面代码中,“返回”首页的Navigator组件,采用NavigationType.Back的类型。上一节教程中,从index.ets页面创建导航采用的是NavigationType.Push的类型。这里重点讲一下NavigationType.Replace的类型。
我们做三个简单的实验,然后得出一些结论:
实验一在NavigatorSample.ets页面启动本地预览器。
注意,不要在本地预览器中先打开了index页面再跳转到NavigatorSample.ets页面,而是,在DevEco Studio中打开NavigatorSample.ets页面,然后启动本地预览器或刷新本地预览器,确保NavigatorSample.ets页面是本地预览器启动的第一个页面,否则实验会不够严谨。
如下左图。然后点击链接,跳转到HyperlinkSample.ets页面。HyperlinkSample.ets页面的返回链接代码如下:
// 返回NavigatorSample页面 Row(space:8) Image($r("app.media.ic_back")).width(24).height(24)Navigator( target: pages/NavigatorSample, type: NavigationType.Back ) Text(返回) .fontColor($r("app.color.fgLevel1")) .fontSize($r("app.float.fontSizeH8")) .fontWeight(Number($r("app.float.fontWeightH8")))Blank() .width(100%)

如下右图。然后点击左上角的“返回”,会发生什么?
HarmonyOS - Hyperlink组件和Navigator组件

文章图片

答案是:什么也不会发生。因为上级页面NavigatorSample.ets通过NavigationType.Replace方式路由过来的时候,已经将自己“销毁”了。所以HyperlinkSample.ets页面不知道返回到哪里了,像一个可怜迷路的孩子。
实验二将HyperlinkSample.ets页面的返回链接重新指向首页index.ets(修改Navigator组件的target值为pages/index),代码如下:
// 返回首页 Row(space:8) Image($r("app.media.ic_back")).width(24).height(24)Navigator( target: pages/index, type: NavigationType.Back ) Text(返回) .fontColor($r("app.color.fgLevel1")) .fontSize($r("app.float.fontSizeH8")) .fontWeight(Number($r("app.float.fontWeightH8")))Blank() .width(100%)

从NavigatorSample.ets页面启动本地预览器,然后重新做上面的实验,结果也是进入HyperlinkSample.ets页面后点击返回,没反应。
实验三然后,我们在index.ets页面启动本地预览器,点击首页中的" 4.Navigator组件" ,使用NavigationType.Push的方式跳转到NavigatorSample.ets页面,然后点击“用Hyperlink页面替换当前页面”,使用NavigationType.Replace方式进入HyperlinkSample.ets页面,然后点击“返回”,会发生什么?
HarmonyOS - Hyperlink组件和Navigator组件

文章图片

虽然NavigatorSample.ets页面已经销毁了,找不上了,但是“它爸还在”,返回了index.ets页面。
结论1.如果通过NavigationType.Replace方式从A页面进入B页面,那么不要在B页面中通过NavigationType.Back的方式返回页面A(参考实验一)。当然,如果在页面B的Navigator组件中只写target指向页面A,不写可选参数type,那么可以进入页面A(但不是返回),此时,不是唤醒了页面A,而是重新启动了新的页面A。大家可以观察一下,通过有效的NavigationType.Back返回页面时,页面从手机等设备的左侧滑回屏幕中,如果是新进入一个页面,是从设备右侧滑入屏幕中。
2.使用NavigationType.Back的方式返回某页面时,该页面可以在后台,但不能是被销毁的或未启动过的,否则无法返回。实验二中通过NavigatorSample.ets页面启动预览器(index.ets页面并未启动),虽然target指向pages/index,但不满足NavigationType.Back的条件,也是无法返回的。
3.页面A通过NavigationType.Replace方式进入页面B有两个含义:A页面销毁,同时B取代A的位置。所以实验三中从index.ets页面PUSH到NavigatorSample.ets页面,然后通过Replace方式进入HyperlinkSample.ets页面,等价于从index.ets页面PUSH到HyperlinkSample.ets页面,所以从HyperlinkSample.ets页面返回首页是可以的。
Navigator组件的属性接下来,讲解Navigator的两个属性 active 和params 。
active:当前路由组件是否处于激活状态,处于激活状态时,会生效相应的路由操作。
【HarmonyOS - Hyperlink组件和Navigator组件】官方示范代码:
// Navigator Page @Entry @Component struct NavigatorExample @State active: boolean = false @State Text: string = newsbuild() // .....此处代码省略......Navigator() Text(Back to previous page).width(100%).textAlign(TextAlign.Center) .active(this.active) .onClick(() => this.active = true ) .height(150).width(350).padding(35)

根据我的测试,目前这个active属性不起作用。我使用如下代码,点击后仍然会回退到上一页:
/** * 属性: * .active(boolean):当前路由组件是否处于激活状态,处于激活状态时,会生效相应的路由操作。 */ Navigator() Text(Back to previous page).width(100%).textAlign(TextAlign.Center) .active(false) // 疑似目前该属性没作用,等待release版的表现

params:跳转时要同时传递到目标页面的数据,可在目标页面使用router.getParams()获得。
示范代码如下:
/** * 属性: * .params(Object):默认值undefined 跳转时要同时传递到目标页面的数据,可在目标页面使用router.getParams()获得。 */ Navigator( target: pages/RouterSample, type: NavigationType.Push ) Text(传递参数示范) .fontColor($r("app.color.info")) .fontSize($r("app.float.fontSizeH8")) .fontWeight(Number($r("app.float.fontWeightH8"))) .decoration( type: TextDecorationType.Underline, color: $r("app.color.info") ).params( info: 大王叫我来巡山 ) // 跳转时要同时传递到目标页面的数据

3.2.3 页面路由router其它组件也可以通过页面路由router接口实现Navigator组件的能力。使用router接口前需要导入模块,代码如下:
import router from @system.router

目前该接口支持设备的情况如下表所示:
HarmonyOS - Hyperlink组件和Navigator组件

文章图片

可以发现router.push、router.replace和router.back可以和Navigator组件对标。本节仅演示router.push接口的使用和通过router接收上一个页面传递的参数:
(示范代码见RouterSample.ets)
// 导入模块 import router from @system.router/** * 页面路由接口router */ @Entry @Component struct RouterSample // 通过router接收上一个页面传递的参数 @State info: string = router.getParams().infobuild() Column(space:8) // 返回首页 Row(space:8) Image($r("app.media.ic_back")).width(24).height(24)Navigator( target: pages/NavigatorSample, type: NavigationType.Back ) Text(返回) .fontColor($r("app.color.fgLevel1")) .fontSize($r("app.float.fontSizeH8")) .fontWeight(Number($r("app.float.fontWeightH8")))/** * 显示接收的参数,并演示router.push用法 */ Button(this.info) // 显示接收的参数 .onClick(() => // 常规组件通常通过onClick事件调用router接口实现页面路由 router.push( // 使用push模式 uri: pages/NavigatorSample, // 转向的目标页面 params:// 同时传参 data: 我想换你的紫金葫芦, , ); ).width(100%).height(100%).backgroundColor($r("app.color.appBg")) // App背景颜色 .padding(top: $r("app.float.spaceTop"), bottom:$r("app.float.spaceBottom"), left:$r("app.float.spaceLeft"), right: $r("app.float.spaceRight")) // 屏幕边缘间隔 .alignItems(HorizontalAlign.Start)

效果如下图所示:
HarmonyOS - Hyperlink组件和Navigator组件

文章图片

其它router接口可参考ArkUI接口文档:
https://developer.harmonyos.com/cn/docs/documentation/doc-references/js-apis-basic-features-routes-0000000000611824
【源码地址:https://gitee.com/cloudev/harmonyos3/tree/master/3.0/BaseComponent 】
注意:由于Getee近日因政策改变,对原来开源的代码都做了需要重新审核的要求。如果大家访问源码时打不开,请过几天再试下。已提交审核。
想了解更多关于开源的内容,请访问:
51CTO 开源基础软件社区
https://ost.51cto.com/#bkwz

    推荐阅读