鸿蒙开发:Navigation路由组件使用由繁入简

简介: 使用了插件和路由库之后,在每个Module下都会生成一个路由配置文件,以Module名字+RouterConfig为文件命名,此路由配置文件,也会在AbilityStage中,通过routerInitConfig方法进行自动配置。

前言


上篇文章,针对Navigation做了简单的分析,无论是静态配置还是动态配置,都有着手动配置的需要,本篇文章就是要解决手动配置,利用路由库和插件实现自动配置的需求。

本篇文章大纲如下:


1、主页面和子页面模版(了解)

2、封装统一路由静态库(了解)

3、分析哪些需要插件自动完成(了解)

4、路由库和插件依赖

5、结合标题栏组件简化模版

6、路由库功能调用

7、简单总结


一、主页面和子页面模版(了解)


Navigation是路由容器组件,一般作为首页的根容器,也就是说,我们只在首页面使用即可,对于所有的子页面使用NavDestination即可,项目中的页面,无外乎首页面和子页面,首页面还好,书写一次即可,而子页面就非常非常的多了,所以,需要针对模版进行抽取。


以下简单贴出两个模版,此模版必须在有统一路由库的基础之上进行使用。


主页面模版:


@Entry
  @Component
  struct Index {
    private pageStack: NavPathStack = new NavPathStack()
    aboutToAppear() {
      RouterModule.createRouter(RouterNameConstants.ENTRY_HAP, this.pageStack);
    }
    @Builder
    routerMap(builderName: string, param: object) {
      RouterModule.getBuilder(builderName).builder(param);
    }
    build() {
      Navigation(this.pageStack) {
        RelativeContainer() {
          //其他UI
        }
        .width('100%')
          .height('100%')
      }.width('100%')
        .height('100%')
        .hideTitleBar(true)
        .navDestination(this.routerMap);
    }
  }


子页面模版:


@Component
  struct TestPage {
    build() {
      Column() {
        Text("子页面")
      }
      .width('100%')
        .height('100%')
    }
  }
@Builder
  export function TestBuilder(value: object) {
    NavDestination() {
      TestPage()
    }
    .hideTitleBar(true)
  }
const builderName = BuilderNameConstants.Test;
if (!RouterModule.getBuilder(builderName)) {
  const builder: WrappedBuilder<[object]> = wrapBuilder(TestBuilder);
  RouterModule.registerBuilder(builderName, builder);
}


以上两个模版,特别是子页面,我们不可能每创建一个页面都要书写这么多冗余代码,显然是不合理的,在路由库和插件依赖一项中,会针对其进行抽取。


二、封装统一路由静态库(了解)


要实现各个动态组件的交互,比如主模块和动态共享包,动态共享包和动态共享包,动态共享包和静态共享包等等之间进行跳转,必须需要一个统一的路由组件库进行桥梁作用,这个库,可以直接放到业务层,主要的作用就是路由的相关功能配置,具体的相关工具,可以看上一篇文章。


三、分析哪些需要插件自动完成


在正常的开发中,针对页面,我们正常书写即可,无须其他的额外配置,路由的操作应该和移动端的路由操作一致,只需要一个简单的注解就可以,那么基于此逻辑,其一、子页面中注册配置,NavDestination配置等等都是可以抽取的。


正常的子页面应该清洁无瑕,就是简单的UI组件,其他的都统统交给插件自己生成,自己实现配置。


@RouterPath("entry_test")
  @Component
  export struct TestPage {
    build() {
      //UI组件
    }
  }


其二,就是每个子页面的动态导入import,在上一篇文章中,是需要手动的在初始化中进行配置,针对这个繁琐的程序,也应该交由插件进行配置。


四、路由库和插件依赖


以上三点只是做一个简单的了解,以哪些模版作为生成,以哪些代码需要抽取,这些步骤都已经做了封装,我们简单看下,封装后的路由功能实现。


第一步,配置依赖项


方式一:在需要Module中的oh-package.json5中设置三方包依赖,配置示例如下:


"dependencies": { "@abner/router": "^1.0.2"}


方式二:在Terminal窗口中,执行如下命令安装三方包,DevEco Studio会自动在工程的oh-package.json5中自动添加三方包依赖。建议:在使用的模块路径下进行执行命令。


ohpm install @abner/router


第二步,配置插件


配置插件前,请务必保障你的所有用到路由的Module都依赖了@abner/router,当然你也可以采用中间件的方式进行依赖。


依赖插件


找到项目中的hvigor目录,在hvigor-config.json5文件中dependencies配置插件。


代码如下:当前版本为:1.0.8


"dependencies": {
  "ohos-router": "1.0.8"
}


执行插件方法,打开根目录中的hvigorfile.ts文件,在plugins数组中导入方法:


plugins:[
  abnerRouter()
]


导包:


import { abnerRouter } from 'ohos-router/router-plugin';


插件完成之后,编译项目,你会发现,每个Module中,都会生成一个路由配置文件,以Module名字+RouterConfig为文件命名。


此路由配置文件为自动生成,无特殊情况下无须改动,当然,再有特殊情况下,你可以进行手动更正。


主页面模版


@Entry
  @Component
  struct Index {
    private navPathStack: NavPathStack = new NavPathStack()
    aboutToAppear() {
      routerInitNavPathStack(this.navPathStack)
    }
    @Builder
    routerMap(builderName: string, param: Object) {
      routerReturnBuilder(builderName).builder(param)
    }
    build() {
      Navigation(this.navPathStack) {
        RelativeContainer() {
          //其他组件
        }
        .height('100%')
          .width('100%')
      }.navDestination(this.routerMap)
    }
  }


子页面模版


子页面没有模版,正常书写UI即可,需要配置一个注解@RouterPath设置一个别名即可,此别名需要模块名字+别名。


@RouterPath("entry_test")
  @Component
  export struct TestPage {
    build() {
      //UI组件
    }
  }


五、路由库功能调用


1、普通跳转


startPage支持自己Module下跳转,同样也支持跨组件模式跳转。


startPage("entry_main") //entry_main和页面注解要一一对应


2、带数据跳转


支持常见的数据传递,比如对象、字符串、数组等等


字符串

startPage("shared_show_params", { param: "一个字符串" })

number

startPage("shared_show_params", { param: 100 })

boolean

startPage("shared_show_params", { param: true })

数组

startPage("shared_show_params", { param: [1, 2, 3, 4, 5, 6] })

对象

startPage("shared_show_params", { param: new SharedBean() })

直接传递对象

startPage("shared_show_params", { param: { "name": "AbnerMing", "age": 20 } })

传递Map

let map = new HashMap<string, Object>()
map.set("name", "AbnerMing")
map.set("age", 18)
startPage("shared_show_params", { param: map })

3、接收参数

通过getRouterParams()方法获取上一个页面传递的数据。

aboutToAppear(): void {
  let params = routerGetParams()
  // let map = params as number//number
  // let map = params?.toString() //string
  // let map = params as boolean //boolean
  // let map = params as string[] //数组
  // let map = params as SharedBean //对象
  // let map = params as HashMap<string, Object>//如果是传递的map,自己遍历即可
}

4、返回上一页面

finishPage()

5、返回指定页面

传递页面路由即可。

finishPageToName("entry_back_01")

6、直接返回首页

routerClearPage()

7、返回带数据

跳转时,使用result进行监听返回的参数

startPage("static_return_params", {
  result: (params) => {
    //获取返回的数据
    console.log("==========" + params?.toString())
  }
})

销毁页面时携带返回数据即可。

finishPage({ param: "我是返回的数据" })

8、关于生命周期

当子组件使用了NavDestination之后,会和组件的生命周期发生冲突,为解决这个问题,大家可以使用NavDestination的生命周期进行解决。

目前提供了setRouterLifeCycle方法用于监听其生命周期,可以在子页面中进行实现。

案例如下:

aboutToAppear(): void {
  setRouterLifeCycle({
    onShown: () => {
      console.log("==========显示")
    },
    onHidden: () => {
      console.log("==========隐藏")
    }
  })
    }

相关方法一览:

方法

概述

onWillAppear

NavDestination创建后,挂载到组件树之前执行,在该方法中更改状态变量会在当前帧显示生效

onAppear

通用生命周期事件,NavDestination组件挂载到组件树时执行。

onWillShow

NavDestination组件布局显示之前执行,此时页面不可见(应用切换到前台不会触发)。

onShown

NavDestination组件布局显示之后执行,此时页面已完成布局。

onWillHide

NavDestination组件触发隐藏之前执行(应用切换到后台不会触发)。

onHidden

NavDestination组件触发隐藏后执行(非栈顶页面push进栈,栈顶页面pop出栈或应用切换到后台)

onWillDisappear

NavDestination组件即将销毁之前执行,如果有转场动画,会在动画前触发(栈顶页面pop出栈)

onDisappear

通用生命周期事件,NavDestination组件从组件树上卸载销毁时执行。

三、常见方法汇总

方法

参数

概述

startPage

builderName: string, model?: RouterModel

跳转页面

replacePage

builderName: string, model?: RouterModel

替换页面栈操作

startPageByName

name: string, param: Object, onPop: Callback<PopInfo>, animated?: boolean

将name指定的NavDestination页面信息入栈,传递的数据为param,添加onPop回调接收入栈页面出栈时的返回结果,并进行处理。

startPageDestination

info: NavPathInfo, options?: NavigationOptions

将info指定的NavDestination页面信息入栈,使用Promise异步回调返回接口调用结果,具体根据options中指定不同的LaunchMode,有不同的行为。

startPageDestinationByName

name: string, param: Object, onPop: Callback<PopInfo>,animated?: boolean

将name指定的NavDestination页面信息入栈,传递的数据为param,并且添加用于页面出栈时处理返回结果的OnPop回调,使用Promise异步回调返回接口调用结果。

finishPage

model?: PopModel

销毁页面

finishPageToName

name: string, model?: PopModel

回退路由栈到由栈底开始第一个名为name的NavDestination页面。

routerSetInterception

interception: NavigationInterception

设置Navigation页面跳转拦截回调。

routerClearPage

animated?: boolean

清除栈中所有页面

routerGetParentNavPathStack

无参

清除栈中所有页面

routerDisableAnimation

value: boolean

关闭(true)或打开(false)当前Navigation中所有转场动画。

routerMoveIndexToTop

index: number, animated?: boolean

将index指定的NavDestination页面移到栈顶。

routerMoveToTop

name: string, animated?: boolean

将index指定的NavDestination页面移到栈顶

routerPopToIndex

index: number, result: Object, animated?: boolean

回退路由栈到index指定的NavDestination页面,并触发onPop回调传入页面处理结果。

routerRemoveByName

name: string

将页面栈内指定name的NavDestination页面删除。

routerRemoveByIndexes

indexes: Array<number>

将页面栈内索引值在indexes中的NavDestination页面删除。

routerReplacePathByName

name: string, param: Object, animated?: boolean

将当前页面栈栈顶退出,将name指定的页面入栈

routerRemoveByNavDestinationId

navDestinationId: string

将页面栈内指定navDestinationId的NavDestination页面删除。navDestinationId可以在NavDestination的onReady回调中获取,也可以在NavDestinationInfo中获取。

routerInitBuilder

builderName: string, builder: WrappedBuilder<[Object]>

初始化Builder

routerInitConfig

routerConfig?: RouterConfig[]

初始化配置

routerGetParams

无参

获取传递的参数

六、结合标题栏组件简化模版

如果你想结合我的另一个开源库bar进行使用,那么需要更换插件,由ohos-router切换到abner-router,其他都不变

"abner-router": "1.0.0"

依赖之后的模版,就非常的简单了,对于首页面,只需要使用MainView包裹即可。

首页模版

@Entry
  @Component
  struct Index {
    build() {
      RelativeContainer() {
        MainView() {
          //其他组件
        }
      }
      .height('100%')
        .width('100%')
    }
  }

子页面模版

@Component
  struct TestPage {
    build() {
      TitleLayout({
        title:"我是标题"
      }) {
        //任意组件
      }
    }
  }

七、简单总结


使用了插件和路由库之后,在每个Module下都会生成一个路由配置文件,以Module名字+RouterConfig为文件命名,此路由配置文件,也会在AbilityStage中,通过routerInitConfig方法进行自动配置。


子页面注解的作用很简单,用来标记页面的唯一标识,也就是别名,要求格式为:Module名字+下划线+定义的别名。


如entry Module下:entry_test1,entry_test2等等


如test Module下:test_test1,test_test2等等


如果你想对Module下的路由进行统一管理,便于查找路由和修改路由,目前进支持在Module根目录下进行配置。


比如entry目录下,你可以创建任意的管理类EntryRouter:


export class EntryRouter {
  static EntryTest= "entry_test"//测试页面
}


使用不变,直接获取即可。


@RouterPath(EntryRouter.EntryTest)
  @Component
  export struct TestPage {
    build() {
      //UI组件
    }
  }
相关文章
|
1天前
|
存储 人工智能 JavaScript
Harmony OS开发-ArkTS语言速成二
本文介绍了ArkTS基础语法,包括三种基本数据类型(string、number、boolean)和变量的使用。重点讲解了let、const和var的区别,涵盖作用域、变量提升、重新赋值及初始化等方面。期待与你共同进步!
60 47
Harmony OS开发-ArkTS语言速成二
|
2天前
|
索引
鸿蒙开发:自定义一个股票代码选择键盘
金融类的软件,特别是股票基金类的应用,在查找股票的时候,都会有一个区别于正常键盘的键盘,也就是股票代码键盘,和普通键盘的区别就是,除了常见的数字之外,也有一些常见的股票代码前缀按钮,方便在查找股票的时候,更加方便的进行检索。
鸿蒙开发:自定义一个股票代码选择键盘
|
2天前
鸿蒙开发:自定义一个英文键盘
实现方式呢,有很多种,目前采用了比较简单的一种,如果大家采用网格Grid组件实现方式,也是可以的,但是需要考虑每行的边距以及数据,还有最后两行的格子占位问题。
鸿蒙开发:自定义一个英文键盘
|
2天前
|
前端开发 API 数据库
鸿蒙开发:异步并发操作
在结合async/await进行使用的时候,有一点需要注意,await关键字必须结合async,这两个是搭配使用的,缺一不可,同步风格在使用的时候,如何获取到错误呢,毕竟没有catch方法,其实,我们可以自己创建try/catch来捕获异常。
鸿蒙开发:异步并发操作
|
2天前
|
API
鸿蒙开发:实现popup弹窗
目前提供了两种方式实现popup弹窗,主推系统实现的方式,几乎能满足我们常见的所有场景,当然了,文章毕竟有限,尽量还是以官网为主。
鸿蒙开发:实现popup弹窗
|
2天前
|
开发框架 物联网 API
HarmonyOS开发:串行通信开发详解
在电子设备和智能系统的设计中,数据通信是连接各个组件和设备的核心,串行通信作为一种基础且广泛应用的数据传输方式,因其简单、高效和成本效益高而被广泛采用。HarmonyOS作为一个全场景智能终端操作系统,不仅支持多种设备和场景,还提供了强大的开发框架和API,使得开发者能够轻松实现串行通信功能。随着技术的不断进步,串行通信技术也在不断发展。在HarmonyOS中,串行通信的开发不仅涉及到基本的数据发送和接收,还包括设备配置、错误处理和性能优化等多个方面。那么本文就来深入探讨在HarmonyOS中如何开发串行通信应用,包括串行通信的基础知识、HarmonyOS提供的API、开发步骤和实际代码示例
16 2
|
2天前
鸿蒙语言开发 几十套鸿蒙ArkTs app毕业设计及课程作业
鸿蒙语言开发 几十套鸿蒙ArkTs app毕业设计及课程作业
13 1
|
移动开发 Ubuntu 网络协议
嵌入式linux/鸿蒙开发板(IMX6ULL)开发 (二)Ubuntu操作入门与Linux常用命令(中)
嵌入式linux/鸿蒙开发板(IMX6ULL)开发 (二)Ubuntu操作入门与Linux常用命令
179 1
嵌入式linux/鸿蒙开发板(IMX6ULL)开发 (二)Ubuntu操作入门与Linux常用命令(中)
|
XML Web App开发 开发框架
鸿蒙开发入门 | 开发第一个鸿蒙应用+页面跳转
准备好鸿蒙开发环境后,接下来就需要创建鸿蒙项目,掌握项目的创建过程以及配置。项目创建好后,需要把项目运行在模拟器上,鸿蒙的模拟和安卓模拟器有些不同,鸿蒙提供远程模拟器和本地模拟器,通过登录华为账号登录在线模拟器,使用DevEco Studio可将项目部署到远程模拟器中。
1293 1
鸿蒙开发入门 | 开发第一个鸿蒙应用+页面跳转
|
存储 Ubuntu 前端开发
嵌入式linux/鸿蒙开发板(IMX6ULL)开发 (二)Ubuntu操作入门与Linux常用命令(下)
嵌入式linux/鸿蒙开发板(IMX6ULL)开发 (二)Ubuntu操作入门与Linux常用命令
349 0
嵌入式linux/鸿蒙开发板(IMX6ULL)开发 (二)Ubuntu操作入门与Linux常用命令(下)

热门文章

最新文章