操作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 = new NavPathStack()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
并导出:
@Builder
export function Page3Builder() {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
,否则跳过去也是白屏。
@Builder
export function Page3Builder() {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
@Builder
export function Page3Builder(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
:
@Builder
NavBar() {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奖金)
相关文章:

操作ArkTS页面跳转及路由相关心得
本文为JS老狗原创。 当前端不得不关注的点:路由,今天聊一聊鸿蒙相关的一点心得。 总体上套路不意外,基本就是(尤其是Web)前端那些事:维护路由表、跳转带参数、历史堆栈操作,等等。 历史原因&…...
Vue2-低版本编译兼容-基础语法-data-methods-双向数据绑定v-model
文章目录 1.安装编译命令2.低版本兼容3.vue2响应式数据3.1.data定义3.2.双向数据绑定v-model3.3.单向数据绑定v-bind4.方法methods5.子组件向父组件传值6.父组件向子组件传值1.安装编译命令 命令行工具 vue create zhiliaoplugins8824barcodebatch cd zhiliaoplugins8824barc…...
提取“c语言的函数定义“脚本
------------------------------------------------------------ author: hjjdebug date: 2024年 08月 11日 星期日 16:35:31 CST description: 提取c语言的函数定义脚本 ------------------------------------------------------------ c 文件中包含很多函数定义, 我想在每…...
pytorch学习(十二):对现有的模型进行修改
以VGG16为例: VGG((features): Sequential((0): Conv2d(3, 64, kernel_size(3, 3), stride(1, 1), padding(1, 1))(1): ReLU(inplaceTrue)(2): Conv2d(64, 64, kernel_size(3, 3), stride(1, 1), padding(1, 1))(3): ReLU(inplaceTrue)(4): MaxPool2d(kernel_size2…...
服务器虚拟内存是什么?虚拟内存怎么设置?
服务器虚拟内存是计算机系统内存管理的一种重要技术,它允许应用程序认为它们拥有连续且完整的内存地址空间,而实际上这些内存空间是由多个物理内存碎片和外部磁盘存储器上的空间共同组成的。当物理内存(RAM)不足时,系统…...

深度学习入门指南(1) - 从chatgpt入手
2012年,加拿大多伦多大学的Hinton教授带领他的两个学生Alex和Ilya一起用AlexNet撞开了深度学习的大门,从此人类走入了深度学习时代。 2015年,这个第二作者80后Ilya Sutskever参与创建了openai公司。现在Ilya是openai的首席科学家,…...
Python学习笔记(六)
""" 演示对序列进行切片操作 """ # 切片;从一个序列中,取出一个子序列 # 语法[起始下标:结束下标:步长] # 这三个都不写也行,视为从头到尾步长为1 # 起始下标不写,视作从头开…...

大数据安全规划总体方案(45页PPT)
方案介绍: 大数据安全规划总体方案的制定,旨在应对当前大数据环境中存在的各类安全风险,包括但不限于数据泄露、数据篡改、非法访问等。通过构建完善的安全防护体系,保障大数据在采集、存储、处理、传输、共享等全生命周期中的安…...

第20周:Pytorch文本分类入门
目录 前言 一、前期准备 1.1 环境安装导入包 1.2 加载数据 1.3 构建词典 1.4 生成数据批次和迭代器 二、准备模型 2.1 定义模型 2.2 定义示例 2.3 定义训练函数与评估函数 三、训练模型 3.1 拆分数据集并运行模型 3.2 使用测试数据集评估模型 总结 前言 …...

记一次 SpringBoot2.x 配置 Fastjson请求报 internal server 500
1.遇到的问题 报错springboot从2.1.16升级到2.5.15,之后就报500内部错误,后面调用都是正常的,就考虑转换有错。 接口返回错误: 2.解决办法 因为我用了fastjson,需要转换下,目前可能理解就是springboot-we…...
OSPF笔记
OSPF:开放式最短路径优先协议 使用范围:IGP 协议算法特点:链路状态型路由协议,SPF算法 协议是否传递网络掩码:传递网络掩码 协议封装:基于ip协议封装,协议号为89 一,ospf特点 1…...
IOC容器初始化流程
IOC容器初始化流程 一、概要1.准备上下文prepareRefresh()2. 获取beanFactory:obtainFreshBeanFactory()3. 准备beanFactory:prepareBeanFactory(beanFactory)4. 后置处理:postProcessBeanFactory()5. 调用bean工厂后置处理器:invokeBeanFactoryPostProcessors()6. 注册bea…...

第二季度云计算市场份额榜单:微软下滑,谷歌上升,AWS仍保持领先
2024 年第二季度,随着企业云支出达到 790 亿美元的新高,三大云计算巨头微软、谷歌云和 AWS的全球云市场份额发生了变化。 根据新的市场数据,以下是 2024 年第二季度全球云市场份额结果和六大世界领先者,其中包括 AWS、阿里巴巴、…...
三点确定圆心算法推导
已知a,b,c三点求过这三点的圆心坐标 a ( x 1 , y 1 ) a(x_1, y_1) a(x1,y1) 、 b ( x 2 , y 2 ) b(x_2, y_2) b(x2,y2) 、 c ( x 3 , y 3 ) c(x_3, y_3) c(x3,y3) 确认三点是否共线 叉积计算方式 v → ( X 1 , Y 1 ) u → ( X 2 , Y 2 ) X 1 Y 2 − X 2 Y 1 \…...

神经网络 (NN) TensorFlow Playground在线应用程序
神经网络 (NN) 历史上最重要的发现之一是神经网络 (NN) 的强大功能。 在神经网络中,称为神经元的许多数据层被添加在一起或相互堆叠以计算新的数据级别。 常用的简称: DNN 深度神经网络CNN 卷积神经网络RNN 循环神经网络 神经元 科学家一致认为&am…...
腾讯课堂 离线m3u8.sqlite转成视频
为了广大腾讯课堂用户对于购买的课程不能正常离线播放,构成知识付费损失,故出此文档。 重点:完全免费!!!完全免费!!!完全免费!!! 怎么…...
Linux多路转接
文章目录 IO模型多路转接select 和 pollepoll IO模型 在还在学习语言的阶段,C里使用cin,或者是C使用scanf的时候,总是要等着我们输入数据才执行,这种IO是阻塞IO。下面是比较正式的说法。 阻塞IO: 在内核将数据准备好之前…...

IDEA导入Maven项目的流程配置以常见问题解决
1. 前言 本文主要围绕着在IDEA中导入新Maven项目后的配置及常见问题解决来展开说说。相关的部分软件如下: IntelliJ IDEA 2021.1JDK 1.8Window 2. 导入Maven项目及配置 2.1 导入Maven项目 下面介绍了直接打开本地项目和导入git上的项目两种导入Maven方式。 1…...

【数据分析---- Pandas进阶指南:核心计算方法、缺失值处理及数据类型管理】
前言: 💞💞大家好,我是书生♡,本阶段和大家一起分享和探索数据分析,本篇文章主要讲述了:Pandas进阶指南:核心计算方法、缺失值处理及数据类型管理等等。欢迎大家一起探索讨论&#x…...

2024世界机器人大会将于8月21日至25日在京举行
2024年的世界机器人大会预定于8月21日至25日,在北京经济技术开发区的北人亦创国际会展中心隆重举办。 本届大会以“共育新质生产力 共享智能新未来”为核心主题,将汇聚来自全球超过300位的机器人行业专家、国际组织代表、杰出科学家以及企业家࿰…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...

LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...

如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...

DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...

网站指纹识别
网站指纹识别 网站的最基本组成:服务器(操作系统)、中间件(web容器)、脚本语言、数据厍 为什么要了解这些?举个例子:发现了一个文件读取漏洞,我们需要读/etc/passwd,如…...
Webpack性能优化:构建速度与体积优化策略
一、构建速度优化 1、升级Webpack和Node.js 优化效果:Webpack 4比Webpack 3构建时间降低60%-98%。原因: V8引擎优化(for of替代forEach、Map/Set替代Object)。默认使用更快的md4哈希算法。AST直接从Loa…...

PHP 8.5 即将发布:管道操作符、强力调试
前不久,PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5!作为 PHP 语言的又一次重要迭代,PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是,借助强大的本地开发环境 ServBay&am…...