0


操作ArkTS页面跳转及路由相关心得

本文为JS老狗原创。

当前端不得不关注的点:路由,今天聊一聊鸿蒙相关的一点心得。

总体上套路不意外,基本就是(尤其是Web)前端那些事:维护路由表、跳转带参数、历史堆栈操作,等等。

历史原因,ArkTS提供了两套方案:router和Navigation。我厂进入比较早,还是采用的router方案;Navigation的方案只是个人大致研究了一下。下面分别聊一聊。

使用@ohos.router

通过路由地址跳转

当我们以下图的路径创建页面时,开发工具会自动记录一个页面路由:

在这里插入图片描述
在这里插入图片描述

文件路径:

src/main/resources/base/profile/main_pages.json

在这里插入图片描述

同一module中,我们可以使用

@ohos.router

库快速实现页面跳转:

import router from'@ohos.router';@Entry@Component
struct Index {build(){Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }){Button('Page1').onClick(()=>{
                router.pushUrl({ url:'pages/Page1'})})}.width('100%').height('100%')}}

效果如下:

在这里插入图片描述

这个操作过程,跟小程序的创建页面和自动记录路由的过程非常类似,跳转过程跟各路

router

也差不多。

当然我们也可手动创建文件,以及手工维护这个路由表。

通过路由命名跳转

我们可以在

@Entry

装饰器上,对页面进行路由命名:

@Entry({ routeName: 'Page2' })
@Component
struct Page2 {
    @State message: string = 'Page2';

    build() {
        RelativeContainer() {
            Text(this.message)
                .id('Page2HelloWorld')
                .fontSize(50)
                .fontWeight(FontWeight.Bold)
                .alignRules({
                    center: { anchor: '__container__', align: VerticalAlign.Center },
                    middle: { anchor: '__container__', align: HorizontalAlign.Center }
                })
        }
        .height('100%')
        .width('100%')
    }
}

然后在索引页面上,

import

这个页面,通知注册路由名称:

import router from'@ohos.router';import'./Page2'// ...

这里只是为了注册

routeName

,需要代码层

import

一个页面,并不是很优雅。

另外还有一种

import('./Page2.ets')

的方式,意思差不多,只是这里算动态引用。我们在某些windows模拟器上发现只能使用这种动态引用,复现不稳定,如有问题可试试这种方式。

新增一个按钮,使用

router.pushNamedRoute

Page2

跳转:

Button('Page2').onClick(() =>{router.pushNamedRoute({name:'Page2'})})

看下效果:

在这里插入图片描述

由于路由表是维护在module内的,所以当时项目使用多module时,使用routeName跳转会比较方便。唯一的缺点就是需要额外import页面。

参数传递

跳转时代入

params

,用于传递参数:

router.pushUrl({ url:'pages/Page1',params:{ productId:'123'}})

在目标页,使用

router.getParams()

获取参数:

import router from'@ohos.router';@Entry@Component
struct Page1 {@State message:string='Page1';@State productId:string=''onPageShow():void{const params =(router.getParams()||{})as Record<string, Object>this.productId =`${params.productId ||''}`}build(){// ...}}

在这里插入图片描述

请注意

router.getParams()

又可能返回

null

,取值请注意降级。

另外,上面例子是在

onPageShow

阶段获取,如果是从其他页面back回来的,这种方式有可能会导致页面参数取值错误。

使用NavPathStack+Navigation

其中

NavPathStack

是路由堆栈,

Navigation

是UI组件,可以快捷实现页头、底部tabBar等功能能。两者必须结合使用。

构建索引页

我们把

Index

页面重构一下:

import router from'@ohos.router';import'./Page2'@Entry@Component
struct Index {
    routeStack =newNavPathStack()build(){Navigation(this.routeStack){Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }){Button('Page1').onClick(()=>{
                    router.pushUrl({ url:'pages/Page1'})}).margin({ bottom:10})Button('Page2').onClick(()=>{
                    router.pushNamedRoute({ name:'Page2'})}).margin({ bottom:10})}.width('100%').height('100%')}}}

由于我们未对

Navigation

组件做任何配置,所以现在页面看不出变化。

维护路由表

这个过程可以简单分3步,请依次完成。首先打开冰箱……

1、创建

Page3

,仅用

@Component

装饰;使用

Page3

构建一个

@Builder

声明为

Page3Builder

并导出:

@BuilderexportfunctionPage3Builder(){Page3()}@Component
struct Page3 {@State message:string='Page3';build(){RelativeContainer(){Text(this.message)//...}.height('100%').width('100%')}}

2、在目录

src/main/resources/base/profile

中,创建文件

route_map.json

,指向上面的

Page3

,命名为

page3

这里的命名建议不要区分大小写,比如驼峰什么的就算了,全小写+数字+下划线不容易出错。

{"routerMap":[{"name":"page3","pageSourceFile":"src/main/ets/pages/Page3.ets","buildFunction":"Page3Builder"}]}

3、将路由表在

module.json5

中注册:

{"module":{// ..."routerMap":"$profile:route_map"// ...}}

4、没想到吧,其实这一步最重要了:使用

NavDestination

包裹

Page3

,否则跳过去也是白屏。

@BuilderexportfunctionPage3Builder(){Page3()}@Component
struct Page3 {@State message:string='Page3';build(){NavDestination(){RelativeContainer(){Text(this.message).id('Page3HelloWorld').fontSize(50).fontWeight(FontWeight.Bold).alignRules({
                        center:{ anchor:'__container__', align: VerticalAlign.Center },
                        middle:{ anchor:'__container__', align: HorizontalAlign.Center }})}.height('100%').width('100%')}}}

5、对其实还有一步:在索引页中发起跳转:

Button('Page3').onClick(()=>{this.routeStack.pushPath({ name:'page3'})}).margin({ bottom:10})

在这里插入图片描述

注意这里的跳转名应当严格一致。

看下效果:

在这里插入图片描述

当然你一定发现了,

Page3

的左上角有个返回按钮,这就是

NavDestination

的效果之一。**

Navigation

相关的路由跳转,现在是官方的推荐做法。**

参数传递

在这里插入图片描述

哎,令人无奈。两个槽点:

  • 哪里冒出来的unknown类型;
  • router的参数名是params,怎么这里又成了param

改造

Page3
@BuilderexportfunctionPage3Builder(name:string, param: Object){Page3({ param })}@Component
struct Page3 {@State message:string='Page3';@State product:string=''
    param: Object ={}as Record<string, Object>build(){NavDestination(){RelativeContainer(){Text(`${this.message} - ${Reflect.get(this.param,'product')||''}`)//...}.height('100%').width('100%')}}}

请注意

Page3Builder

的参数传递,以及在

Page3

构建时传入的参数。

另外也可在

NavDestination.onReady

周期获取上下文,从上下文中拿到参数:

build(){NavDestination(){// 。。。}.onReady(context=>{this.product = Reflect.get(context.pathInfo.param,'product')})}

别问

Reflect.get

是啥,用就是了。

Navigation的UI配置

Navigation

的UI配置非常丰富,可以看出这个组件在开发时对各路路由UI都做了充分的调研,用起来让人觉得简单得有点不敢相信。

构建页头

最简单的,给页头起个名字,并设置页头大小。

@Entry
@Component
struct Index {
    routeStack = new NavPathStack()
    build() {
        Navigation(this.routeStack) {
            Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
                // ...
            }
            .width('100%').height('100%')
            .backgroundColor('#fff')
        }
        .title('首页')
        .titleMode(NavigationTitleMode.Mini)
        .backgroundColor('#f1f1f1')
    }
}

看下效果:

在这里插入图片描述

这里

titleMode

的枚举值有:

  • NavigationTitleMode.Mini

在这里插入图片描述

  • NavigationTitleMode.Full / NavigationTitleMode.Free

在这里插入图片描述

自定义UI的页头

在页面中写个

@Builder

@BuilderNavBar(){Flex({
        direction: FlexDirection.Column,
        justifyContent: FlexAlign.Center,
        alignItems: ItemAlign.Center,}){Text('首页').fontSize(16)}.width('100%').height('100%').position({ x:0}).zIndex(-1)}

build()

中输入这个自定义页头:

build(){Navigation(this.routeStack){Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }){Button('Page1').onClick(()=>{
                router.pushUrl({ url:'pages/Page1'})}).margin({ bottom:10})Button('Page2').onClick(()=>{
                router.pushNamedRoute({ name:'Page2'})}).margin({ bottom:10})Button('Page3').onClick(()=>{this.routeStack.pushPath({ name:'page3'})}).margin({ bottom:10})}.width('100%').height('100%').backgroundColor('#fff')}.title(this.NavBar)// <<<<------- 看这里.titleMode(NavigationTitleMode.Mini).backgroundColor('#f1f1f1')}

在这里插入图片描述

请注意

NavBar

中用了一个

zIndex(-1)

,这样就不会遮挡返回按钮了。

底部TabBar配置

先看下效果:

在这里插入图片描述

toolbarConfiguration

build() {
    Navigation(this.routeStack) {
        // ...
    }
    .title(this.NavBar)
    .titleMode(NavigationTitleMode.Mini)
    .backgroundColor('#f1f1f1')
    .toolbarConfiguration([
        {
            icon: 'https://res.suning.cn/project/cmsWeb/suning/homepage/v8/css/images/tool-logo.png',
            value: '首页',
            action: () => {
                router.pushUrl({ url: 'pages/Page1' })
            }
        },
        {
            icon: 'https://image.suning.cn/uimg/cms/img/157105762930982264.png',
            value: '购物车',
            action: () => {
                this.routeStack.pushPath({ name: 'page3' })
            }
        },
        {
            icon: 'https://image.suning.cn/uimg/cms/img/157105768303272975.png',
            value: '我的',
            action: () => {
                router.pushNamedRoute({ name: 'Page2' })
            }
        }
    ])
}

简简单单,配置icon/value/action,即出成品。

写在最后

这个阶段对路由的研究,大致就是如此。感觉像

Navigation

在UI方面的表现,应该还有不少可以深挖的地方。

前面也有大佬们提过,ArkTS跟Flutter像,以及模式、架构跟mvvm也有相近之处,到了路由这部分,其实跟rn也有些相似了。

作为后来者,相信ArkTS能够吸取众家之长,成为集大成者。

关于OpenTiny

欢迎加入 OpenTiny 开源社区。添加微信小助手:opentiny-official 一起参与交流前端技术~
OpenTiny 官网:https://opentiny.design/
TinyVue 源码:https://github.com/opentiny/tiny-vue
TinyEngine 源码: https://github.com/opentiny/tiny-engine
OpenTiny HUICharts 源码:https://github.com/opentiny/tiny-charts
欢迎进入代码仓库 Star🌟TinyEngine、TinyVue、TinyNG、TinyCLI~ 如果你也想要共建,可以进入代码仓库,找到 good first issue标签,一起参与开源贡献~

(温馨提示:OpenTiny CCF开源创新大赛也在持续报名中,欢迎大家一起报名参赛,赢取10W奖金)


本文转载自: https://blog.csdn.net/OpenTiny/article/details/141030244
版权归原作者 OpenTiny社区 所有, 如有侵权,请联系我们删除。

“操作ArkTS页面跳转及路由相关心得”的评论:

还没有评论