快速入门HarmonyOS应用开发(一)

目录

前言

一、准备工作

二、实战开发

2.1、Navigation简介

2.2、页面路由开发

2.2.1、创建常量

2.2.2、创建字符串资源

2.2.3、创建float资源

2.2.4、创建color资源

2.2.5、创建数据实体

2.2.6、创建页面路由表

2.2.7、创建Navigation根容器

2.2.8、创建NavDestination子页面

2.2.9、页面路由跳转及传参

2.2.10、处理页面返回键

前言

写这个系列的目标是准备通过几篇文章的介绍,和大家一起快速入门HarmonyOS应用的开发。初步打算是主要通过代码实战的形式去介绍,基本的语法和使用还是建议大家先阅读官网的文档说明。OK,话不多说,咱们开始。

一、准备工作

首先,最全面的学习资料肯定是官网文档,所以需要快速掌握文档的对应位置,这里把开发中经常用到文档入口都罗列在下面了,按需自取:

开发指南         API文档         最佳实践         FAQ        示例代码

其次,注意搜索时左侧菜单可以选择类别,比如这里可以勾选全部:

OK,接着咱们下载开发工具:下载与安装DevEco Studio,这个没什么好说的,下载完了之后一步一步安装即可。

接着学习开发语言可以参考如下内容,鸿蒙中使用的ArkTS是基于TypeScript做了扩展:

学习ArkTS语言和应用框架中的ArkTs(方舟编程语言)

准备工作就做到这里,接下来就可以上手开发了,今天咱们首先来学习路由如何使用。

二、实战开发

2.1、Navigation简介

Navigation主要用于实现Navigation页面(NavDestination)间的跳转,支持在不同Navigation页面间传递参数,提供灵活的入栈出栈操作,方便快捷的实现对不同页面的访问和复用。关于Navigation更多的介绍及详细使用大家可以参考:

组件导航(Navigation) (推荐)

2.2、页面路由开发

首先我们先创建一个空工程,这里可以根据公司规范或者个人习惯修改相关文件名。在src/main/ets/pages目录下新建navigation文件夹,将Index.ets移动到该文件夹下,并修改文件名为NavigationPage.ets,并且修改代码中Index名称为NavigationPage,同时还需要修改EntryAbility文件中默认加载的页面路径:

上面的NavigationPage作为整个工程页面路由栈的根页面,你可以把它理解为一个相册,我们使用@Entry来修饰它,并且使用Navigation作为它的组件树的根节点。然后我们需要实现的APP的各个展示页面就是相册里面的一张一张的照片,我们使用@Component来修饰它,并且使用NavDestination作为它们的组件树的根节点。简单理解就是:Navigation是容器,NavDestination是页面。在今天的例子中,我们会创建两个页面MainPage和OtherPage。

今天由于是本系列的第一篇,所以一些基础工作我也会介绍一下,后续的文章中将不再赘述。

2.2.1、创建常量

在工程的src/main/ets 目录下新建文件夹constants,用来存放项目中需要用到的常量字段,这里我们创建两个文件:CommonConstant存放公共常量,PageConstant存放页面名称,代码如下:

export class CommonConstant {static readonly FULL_PERCENT: string = '100%'static readonly PAGEINFO_KEY: string = 'PageInfo'static readonly EXIT_INFO: string = '再按一次退出应用'static readonly PRE_TIME: number = 0static readonly EXIT_TIME: number = 2000
}
export class PageConstant{static readonly PAGE_MAIN: string = 'MainPage'static readonly PAGE_OTHER: string = 'OtherPage'
}

2.2.2、创建字符串资源

在resources/base/elment/string.json文件中添加项目中需要用到的字符串资源:

{"string": [{"name": "tip_main_page","value": "我是主页点我跳转"},{"name": "tip_other_page","value": "我是其它页面"}]
}

2.2.3、创建float资源

在resources/base/elment/float.json文件中添加项目中需要用到的字体大小fp和组件大小vp资源:

{"float": [{"name": "fp_20","value": "20fp"},{"name": "vp_100","value": "100vp"}]
}

2.2.4、创建color资源

在resources/base/elment/color.json文件中添加项目中需要用到的颜色资源:

{"color": [{"name": "color_primiry","value": "#57BE6A"}]
}

2.2.5、创建数据实体

在src/main/ets下新建model文件夹,在该文件夹下新建DemoData.ets文件,在这个文件里我们创建页面间传值所需的数据类,这里介绍了两种方式interface和class,都可以定义所需的实体:

// MainPage传递参数的数据类
export interface ParamData {name: string
}// OtherPage回传的数据类
export class BackData {result?: stringconstructor(result: string) {this.result = result}
}

2.2.6、创建页面路由表

在src/main/ets/pages/navigaion目录下新建PagesMapBuilder.ets文件,作为项目的页面路由表:

import { PageConstant } from "../../constants/PageConstant";
import { MainPage } from "../MainPage";
import { OtherPage } from "../OtherPage";@Builder
export function PagesMapBuilder(name: string) {if (name===PageConstant.PAGE_MAIN) {MainPage()}else if (name===PageConstant.PAGE_OTHER){OtherPage()}
}

2.2.7、创建Navigation根容器

在NavigationPage页面中,我们实例化了一个NavPathStack对象:

// 页面路由栈
@Provide(CommonConstant.PAGEINFO_KEY) pageStack: NavPathStack = new NavPathStack()

从名字也能看出它是用来管理页面路由的路由栈对象,这里我们使用了@Provide这个装饰器来修饰,它一般是与@Consume成对使用,用于与后代组件的双向数据同步、状态数据在多个层级之间传递的场景。使用详情可以参考:@Provide装饰器和@Consume装饰器:与后代组件双向同步

然后在build()函数中,我们创建Navigation组件并且绑定导航控制器和页面路由表:

import { CommonConstant } from '../../constants/CommonConstant'
import { PagesMapBuilder } from './PagesMapBuilder'@Entry
@Component
struct NavigationPage {// 页面路由栈@Provide(CommonConstant.PAGEINFO_KEY) pageStack: NavPathStack = new NavPathStack()build() {Navigation(this.pageStack).hideTitleBar(true).hideToolBar(true).hideNavBar(true).mode(NavigationMode.Stack).navDestination(PagesMapBuilder)}
}

这里的build()函数是用于定义自定义组件的声明式UI描述,自定义组件必须定义build()函数。从这里也就看出了HarmonyOS应用的UI是使用的声明式UI,这里提到了它是用于自定义组件的UI描述,因此咱们这里的NavigationPage也是自定义组件,你可以理解在HarmonyOS应用中:一切皆组件!

关于自定义组件的使用可以参考:创建自定义组件

可以看到,我们代码中的@Component  struct正是符合这个结构的,至于最上面的@Entry,那是因为它装饰的自定义组件是UI页面的入口。

2.2.8、创建NavDestination子页面

在src/main/ets/pages文件夹下新建MainPage.ets文件,在这个文件中首先定义路由栈对象,承接上文中的@Provide,这里我们可以直接使用@Consume来定义:

@Consume(CommonConstant.PAGEINFO_KEY) pageStack: NavPathStack

然后在build()函数中创建NavDestination为根节点的组件树,这里面我们仅添加一个Text文本用于展示:

import { CommonConstant } from "../constants/CommonConstant"@Component
export struct MainPage {@Consume(CommonConstant.PAGEINFO_KEY) pageStack: NavPathStack@State content: string | Resource = $r('app.string.tip_main_page')build() {NavDestination() {Column() {Text(this.content).fontSize($r('app.float.fp_20')).fontColor(Color.Blue).fontWeight(FontWeight.Bold)}.width(CommonConstant.FULL_PERCENT).height(CommonConstant.FULL_PERCENT).justifyContent(FlexAlign.Center)}.hideTitleBar(true)}
}

这里的@State同样是一个状态管理的装饰器,用它修饰的变量在组件内数据变更时可以引起UI的自动刷新,具体使用可以参考:@State装饰器:组件内状态

然后以同样的方式创建另一个页面OtherPage.ets:

import { CommonConstant } from "../constants/CommonConstant"@Component
export struct OtherPage {@Consume(CommonConstant.PAGEINFO_KEY) pageStack: NavPathStack@State content: string | Resource = $r('app.string.tip_other_page')build() {NavDestination() {Column() {Text(this.content).fontSize($r('app.float.fp_20')).fontColor(Color.Blue).fontWeight(FontWeight.Bold).onClick(() => {let backData = new BackData('我是Other数据')this.pageStack.pop(backData)})}.width(CommonConstant.FULL_PERCENT).height(CommonConstant.FULL_PERCENT).justifyContent(FlexAlign.Center)}.hideTitleBar(true)}
}

2.2.9、页面路由跳转及传参

首先在NavigationPage的aboutToAppear()回调中添加第一个加载的页面视图:

aboutToAppear(): void {this.pageStack.pushPath({ name: PageConstant.PAGE_MAIN }, false)
}

aboutToAppear()是自定义组件的一个生命周期函数,在组件即将出现时回调该接口,具体时机为在创建自定义组件的新实例后,在执行其build函数之前执行,详情可以参考:

自定义组件生命周期

然后在MainPage中创建需要传递的参数:

paramData: ParamData = { name: '我是MainPage数据' }

在MainPage中的Text文本的点击事件里,跳转到OtherPage页面,并将上面的数据作为参数传递过去,同时在onPop回调中可以接收OtherPage页面回传的参数,如果不需要回传参数onPop回调可以不用写:

.onClick(() => {// 页面跳转,传递参数到Other页面,并通过onPop回调接收Other页面回传的数据this.pageStack.pushPath({name: PageConstant.PAGE_OTHER, param: this.paramData, onPop: (popInfo: PopInfo) => {let backData = popInfo.result as BackDatathis.content = backData.result}})})

接着在OtherPage页面中接收来自MainPage传递的参数,这里接收参数我们介绍两种方式:

第一种:使用NavDestination的onReady()函数进行接收:

.onReady((context: NavDestinationContext) => {this.paramData = context.pathInfo.param as ParamDataif (this.paramData) {this.content = this.paramData.name}})

第二种:在aboutToAppear()生命周期函数中通过pageStack的getParamByIndex()函数接收:

aboutToAppear(): void {this.paramData = this.pageStack.getParamByIndex(this.pageStack.size() - 1) as ParamDataif (this.paramData) {this.content = this.paramData.name}}

然后在OtherPage的Text文本的点击事件中我们将需要回传的参数通过pageStack的pop(xxx)方法进行回传:

.onClick(() => {let backData = new BackData('我是Other数据')this.pageStack.pop(backData)})

2.2.10、处理页面返回键

在Android中我们经常可以看到在点击Back键时会提示:再按一次退出应用,虽然现在很多手机隐藏了返回键,但是我们通过侧滑仍然可以出发页面返回,那如果想要实现上面的效果该怎么做呢?

其实原理是类似的,在HarmonyOS中,我们可以监听页面的onBackPress()事件,在这个函数中处理连续点按退出应用的逻辑:

import { CommonConstant } from '../../constants/CommonConstant'
import { common } from '@kit.AbilityKit'@Entry
@Component
struct NavigationPage {private context = this.getUIContext().getHostContext() as common.UIAbilityContextprivate preTime: number = CommonConstant.PRE_TIMEpromptAction = this.getUIContext().getPromptAction()// 2秒内连续点按/侧滑后关闭当前应用onBackPress(): boolean | void {let currentTime = new Date().getTime()let flag = currentTime - this.preTimeif (flag > CommonConstant.EXIT_TIME) {this.preTime = currentTimethis.promptAction.showToast({ message: CommonConstant.EXIT_INFO })return true} else {this.context.terminateSelf()}return false}
}

最后来看一下实现的效果吧:

实现效果录屏

完整代码:HarmonyDemos

OK,今天的内容到这里就要和大家说再见了,咱们下期再会!

祝:工作顺利,前程似锦!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/99236.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/99236.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI 进课堂 - 语文教学流程重塑

AI 进课堂 - 语文教学流程重塑执教语文十余年,备课案头的参考书堆得比学生作业本还高,批改作文时红笔芯换得比粉笔还勤。 直到去年把 JBoltAI 请进课堂,那些重复机械的工作突然有了新解法,连课堂上孩子们的眼神都亮了许多 —— 这…

用户是否可以同时使用快照和备份来保护云服务器数据安全?

在云计算环境中,云服务器已成为企业和个人数据存储、应用部署和业务运营的重要平台。随着业务数据量的不断增长,数据安全和业务连续性成为用户关注的核心问题。云服务器提供的快照和备份功能为用户提供了有效的数据保护手段,但很多人会疑问&a…

RDS-MYSQL,这个RDS是什么?和mysql有什么区别?

好的,这是一个非常常见且重要的问题。我用最通俗易懂的方式给你解释清楚。 一、大白话解释 你可以把 MySQL 和 RDS MySQL 的关系,想象成:MySQL:就像是你自己买零件组装的一台电脑。 你需要自己挑选CPU、内存、硬盘、主板&#xff…

arcgis中实现四色/五色法制图

四色定理是图论中的一个著名定理,它指出在任何地图上,只需四种颜色就足以使任何相邻的区域(拥有共同边界线段,而非单个点)颜色不同。五色定理则是另一个更早被证明的、较弱但更易证的定理。在地图制图中,这…

Spring如何巧妙解决循环依赖问题

什么是循环依赖?循环依赖是指两个或多个Bean之间相互依赖,形成闭环的情况。例如:AService依赖BService,而BService又依赖AService。这种场景下,传统的创建顺序无法满足依赖注入的要求。Spring的三级缓存机制Spring通过…

CUDA 中Thrust exclusive_scan使用详解

1. 基本概念Thrust 是 NVIDIA CUDA 提供的类似 C STL 的并行算法库。Scan (前缀和):给定数组 [a0, a1, a2, ...],产生前缀和序列。Exclusive Scan (排他前缀和): 输出位置 i 存放的是输入数组中 0 到 i-1 的累积结果。换句话说,结…

Linux -- 信号【上】

目录 一、信号的引入 1、信号概念 2、signal函数 普通标准信号详解表 3、前台/后台进程 3.1 概念 3.2 查看后台进程 3.3 后台进程拉回前台 3.4 终止后台进程 3.5 暂停前台进程 3.6 回复运行后台进程 4、发信号的本质 二、信号的产生 1、终端按键 2、系统调用 2…

Altium Designer(AD)自定义PCB外观颜色

目录 1视图设置界面介绍 2PCB阻焊层颜色设置 2.1进入视图设置界面 2.2阻焊层颜色设置 2.3顶层和底层阻焊层颜色设置 2.4顶层阻焊层试图效果 2.5底层阻焊层试图效果 3设置PCB丝印颜色设置 3.1找到丝印设置选项 3.2设置顶层和底层丝印颜色 3.3顶层丝印 3.4底层丝印 4…

5天改造,节能50%!冷能改造如何实现“不停产节能”?

你有没有发现一个现象?很多工厂老板一提到节能改造,第一反应就是摇头。不是不想省电费,而是怕停产。停产一天损失几十万,改造周期动辄几个月,这账怎么算都不划算。但如果我告诉你,有一种改造方式&#xff0…

【Flink】窗口

目录窗口窗口的概念窗口的分类滚动窗口(Tumbling Windows)滑动窗口(Sliding Windows)会话窗口(Session Windows)全局窗口(Global Windows)窗口API概览窗口函数增量聚合函数ReduceFun…

攻击路径(4):API安全风险导致敏感数据泄漏

本文是《攻防演练 | JS泄露到主机失陷[1]》的学习笔记,欢迎大家阅读原文。攻击路径通过未授权访问攻击获取敏感数据通过SQL注入攻击获取服务器权限通过凭据访问攻击获取数据库权限和敏感数据和应用权限安全风险与加固措施通过未授权访问攻击获取敏感数据、通过SQL注…

机器学习面试题:请介绍一下你理解的集成学习算法

集成学习(Ensemble Learning)的核心思想是“集思广益”,它通过构建并结合多个基学习器(Base Learner)来完成学习任务,从而获得比单一学习器更显著优越的泛化性能。俗话说,“三个臭皮匠&#xff…

Invalid bound statement (not found): com.XXX.XXx.service.xxx无法执行service

org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.xxx.xxx.service.CitytownService.selectCitytown 出现无法加载sevice层的时候,如下图所示1,处理方法是,先看下注解MapperScan内的包地址&#xff0c…

泛型(Generics)what why when【前端TS】

我总是提醒自己一定要严谨严谨严谨 目录TypeScript 泛型 (Generics)1. 什么是泛型?2. 为什么需要泛型?3. 泛型常见用法3.1 函数泛型3.2 接口泛型3.3 类泛型3.4 泛型约束3.5 泛型默认值3.6 多个泛型参数4. 泛型应用场景TypeScript 泛型 (Generics) 1. 什…

分布式协议与算法实战-协议和算法篇

05丨Paxos算法(一):如何在多个节点间确定某变量的值? 提到分布式算法,就不得不提 Paxos 算法,在过去几十年里,它基本上是分布式共识的代名词,因为当前最常用的一批共识算法都是基于它改进的。比…

9.13 9.15 JavaWeb(事务管理、AOP P172-P182)

事务管理事务概念事务是一组操作的集合,是一个不可分割的工作单位,这些操作要么同时成功,要么同时失败操作开启事务(一组操作开始前,开启事务):start transaction / begin提交事务(这…

检索融合方法- Distribution-Based Score Fusion (DBSF)

在信息检索(IR)、推荐系统和多模态检索中,我们常常需要融合来自多个检索器或模型的结果。不同检索器可能对同一文档打出的分数差异很大,如果直接简单加权,很容易出现某个检索器“主导融合结果”的情况。 Distribution…

Oracle体系结构-归档日志文件(Archive Log Files)

核心概念:什么是归档日志文件? 定义: 归档日志文件(Archive Log Files)是在线重做日志文件(Online Redo Log Files)在被覆盖之前的一个完整副本。它们由 Oracle 的后台进程 ARCn(归档…

GoogLeNet实战:用PyTorch实现经典Inception模块

配套笔记&讲解视频,点击文末名片获取研究背景(Background) 1.1 领域现状(大环境与挑战) 想象一下,你和朋友们在看一大堆照片——猫、狗、汽车、蛋糕,大家要把每张照片贴上标签。几年前&…

【开题答辩全过程】以 “旧书驿站”微信小程序的设计与开发为例,包含答辩的问题和答案

个人简介一名14年经验的资深毕设内行人,语言擅长Java、php、微信小程序、Python、Golang、安卓Android等开发项目包括大数据、深度学习、网站、小程序、安卓、算法。平常会做一些项目定制化开发、代码讲解、答辩教学、文档编写、也懂一些降重方面的技巧。感谢大家的…