一节课上手鸿蒙开发
一节课上手鸿蒙开发
作者:兰州大学信息科学与工程学院 钱浩莱、聂嘉一、叶清扬、王天一
注:本博客为兰州大学2024年2022级人工智能暑期学校暨华为开发者布道师活动的部分讲义
简介
只讲干货,不讲废话!!!
本课程主要讲解基础鸿蒙应用开发,可适用于
1.HarmonyOS,适用于华为鸿蒙系统的手机、平板
2.OpenHarmony标准系统应用开发,应用于杂七杂八、各式各样的设备(银行自助设备、工业农业控制设备…)
鸿蒙应用开发环境搭建
下载链接:
安装教程:
https://blog.csdn.net/m0_61802503/article/details/136380063
第一个工程
@Entry
@Component
struct Index {
//@State 是一种装饰器,被它装饰的变量 message 值发生改变时,会触发该变量所对应的自定义组件 Hello 的 UI 界面进行自动刷新。
@State message: string = 'Hello World';
build() {
//Row 相当于一个行容器,表示设置一行
Row() {
//Column相当于一个列容器,表示设置一列
Column() {
Text(this.message) //设置文本及内容
.fontSize(50) //设置字体大小
.fontWeight(FontWeight.Bold) //设置字体宽度,FontWeight.Bold就是粗体,系统定义的宽度
}
.width('100%') //设置宽度占比
}
.height('100%') //设置高度占比
}
}
text、image组件
text组件,就是显示文字
用法:
Text("显示的字符串")
Text(字符串变量名)
相关案例见: demos/TextDemo
image组件,就是显示图片
相关案例见: demos/ImageDemo
用法:
(1)Image(图片文件路径)
(相对于ets目录的路径)
(2)Image($r('app.media.tiger'))
把图片放在 "工程名\entry\src\main\resources\base\media"目录下,这样用法不要加后缀名
(3)Image(网络图片链接,比如http://xxxx.jpg)
组件属性
上面讲了文本组件和图片组件。
每个组件都有各式各样的属性,长宽高、颜色、位置…。我们都可以设置他的属性。
我们用".属性名()"这种方法设置属性。
Text('test').fontSize(12)
Image('test.jpg')
.width(100)
.height(100)
Text('hello')
.fontSize(20)
.fontColor(Color.Red)
.fontWeight(FontWeight.Bold)
属性分为通用属性和特定组件属性
比如宽(width)、高(height)、背景颜色(backgroundColor)这些就是特定属性,像字体颜色(fontColor)就是Text组件的特定属性。(详情见演示)
button、textInput组件,事件处理
button组件就是按钮,点击后会进行相应的功能
常见的用法
Button("名字").onClick(()=>{
执行的函数
......
})
在鸿蒙开发中,组件是构成界面的最小单元,我们所看到的界面,都是由众多组件组合而成的,所以编写界面其实就是组合组件的过程,ArkTS提供了很多的内置组件,例如:Text
、Button
、Image
等等;并且ArkTS还支持自定义组件,让开发者可根据具体需求自定义组件中的内容。
当然,实现按钮不一定需要用按钮组件,其他组件加上点击事件也具有按钮功能
相关案例见: demos/buttonDemo
TextInput组件,就是一个输入框
用法如下,
TextInput({placeholder:"输入提示"}).onChange((value)=>{
输入值改变时,执行的函数,value为输入框中输入的值
})
相关案例见:demos/TextInputDemo
线性布局
概述
线性布局(LinearLayout
)是开发中最常用的布局,可通过容器组件Column
和Row
构建,其子组件会在垂直或者水平方向上进行线性排列,具体效果如下图所示
|
|
说明
Column和Row容器均有两个轴线,分别是主轴和交叉轴
- 主轴:线性布局容器在布局方向上的轴线,
**Row**
容器主轴为横向,**Column**
容器主轴为纵向。 - 交叉轴:垂直于主轴方向的轴线。
**Row**
容器交叉轴为纵向,**Column**
容器交叉轴为横向。
参数
Column和Row容器的参数类型为{space?: string | number}
,开发者可通过space
属性调整子元素在主轴方向上的间距,效果如下
| ||
| | |
相关案例见:demos/LinearLayoutDemo/SpacePage.ets
常用属性
子元素沿主轴方向的排列方式
子元素沿主轴方向的排列方式可以通过justifyContent()
方法进行设置,其参数类型为枚举类型FlexAlign
,可选的枚举值有
名称 | Start |
Center |
End |
SpaceBetween |
SpaceAround |
SpaceEvenly |
---|---|---|---|---|---|---|
描述 | 头部对齐 | 居中对齐 | 尾部对齐 | 均匀分布,首尾两项两端对齐,中间元素等间距分布 | 均匀分布,所有子元素两侧都留有相同的空间 | 均匀分布,所有子元素之间以及首尾两元素到两端的距离都相等 |
效果(以Column容器为例) |
相关案例见:demos/LinearLayoutDemo/JustifyContent.ets
子元素沿交叉轴方向的对齐方式
子元素沿交叉轴方向的对齐方式可以通过alignItems()
方法进行设置,其参数类型,对于Column
容器来讲是HorizontalAlign
,对于Row
容器来讲是VerticalAlign
,两者都是枚举类型,可选择枚举值也都相同,具体内容如下
名称 | Start |
Center |
End |
---|---|---|---|
描述 | 头部对齐 | 居中对齐 | 尾部对齐 |
效果(以Column容器为例) |
相关案例见:demos/LinearLayoutDemo/AlignItemsPage.ets
自定义组件
在鸿蒙开发中,组件是构成界面的最小单元,我们所看到的界面,都是由众多组件组合而成的,所以编写界面其实就是组合组件的过程,ArkTS提供了很多的内置组件,例如:Text
、Button
、Image
等等;并且ArkTS还支持自定义组件,让开发者可根据具体需求自定义组件中的内容。
除去系统预置的组件外,ArkTS 还支持自定义组件。使用自定义组件,可使代码的结构更加清晰,并且能提高代码的复用性。
自定义组件的语法如下图所示
各部分语法说明如下:
**struct**
关键字
struct
是ArkTS新增的用于自定义组件或者自定义弹窗的关键字。其声明的数据结构和TS中的类十分相似,可包含属性和方法。
**build**
方法
build()
方法用于声明自定义组件的UI结构。
- 组件属性
组件属性可用作自定义组件的参数,使得自定义组件更为通用。
**@Compnent**
装饰器
@Component
装饰器用于装饰struct
关键字声明的数据结构。struct
被@Component
装饰后才具备组件化的能力。
页面路由(从单个页面到多个页面)
概述
页面路由用于实现应用程序中不同页面之间的跳转。HarmonyOS提供了router模块,用于实现页面路由功能。通过该模块,开发者可以轻松实现页面跳转、页面返回等功能。
router模块提供了两种跳转模式,分别是router.pushUrl()
和router.replaceUrl()
,这两种模式的区别在于是否保留当前页的状态。pushUrl()
会将当前页面压入历史页面栈,因此使用该方法跳转到目标页面之后,还可以再返回。而replaceUrl()
,会直接销毁当前页面并释放资源,然后用目标页替换当前页,因此使用该方法跳转到目标页面后,不能返回。
上述两方法的基础用法如下:
第一步:注册页面
页面注册后才能进行跳转,具体操作如下,例如现有一个页面的路径为src/main/ets/pages/SourcePage.ets
,我们在src/main/resources/base/profile/main_pages.json
文件增加如下配置即可
{
"src": [
"pages/Index",
"pages/SourcePage", //新增配置
]
}
注意:
在创建页面时,若选择新建Page
而不是ArkTs File
,则IDE会自动完成页面的注册。
第二步:导入router模块
import router from '@ohos.router'
之后便可使用上述两个方法完页面的跳转
router.pushUrl({ url: 'pages/router/pushAndReplace/TargetPage' })
router.replaceUrl({ url: 'pages/router/pushAndReplace/TargetPage' })
相关案例见:Demos/entry/src/main/ets/pages/router/pushAndReplace/SourcePage.ets
页面返回
返回页面使用router.back()
方法即可,直接调用router.back()
将返回上一页面,除此之外该方法也支持返回指定页面,例如
router.back({url:'pages/Index'})
注意:
若指定的页面不在历史页面栈中,也就是用户并未浏览过指定页面,那么将无法回到指定页面。
相关案例见:Demos/entry/src/main/ets/pages/router/back/FromPage.ets
传递数据
在进行页面跳转时,如果需要传递一些数据给目标页面,可以在调用上述方式时,添加一个params
属性,并指定一个对象作为参数,例如
router.pushUrl({
url: 'pages/router/pushAndReplace/TargetPage',
params: {
id: 10,
name: 'zhangsan',
age: '20'
}
})
目标页面可通过router.getParams()
方法获取参数,例如
let params = router.getParams();
let id = params['id'];
let name = params['name'];
let age = params['age'];
相关案例见:Demos/entry/src/main/ets/pages/router/params/StartPage.ets
条件判断控制,一个开灯案例的实现
循环控制渲染
ForEach
循环渲染的语法如下
ForEach(
arr: any[],
itemGenerator: (item: any, index?: number) => void,
keyGenerator?: (item: any, index?: number) => string
)
各参数的含义如下
- arr
需要进行循环渲染的数据源,必须为数组类型,例如上述案例中的
@State options: string[] = ["苹果", "桃子", "香蕉", "橘子"];
- itemGenerator
组件生成函数,用于为arr
数组中的每个元素创建对应的组件。该函数可接收两个参数,分别是
- item:
arr
数组中的数据项 - index(可选):
arr
数组中的数据项的索引
例如上述案例中的
(item: string) => {
Button(item)
.width(100)
.backgroundColor(Color.Green)
.onClick(() => {
this.answer = item;
})
}
- keyGenerator(可选):
key生成函数,用于为arr
数组中的每个数据项生成唯一的key。
key的作用
ForEach
在数组发生变化(修改数组元素或者向数组增加或删除元素)时,需要重新渲染组件列表,在重新渲染时,它会尽量复用原来的组件对象,而不是为每个元素都重新创建组件对象。key的作用就是辅助ForEach
完成组件对象的复用。
具体逻辑如下:
ForEach
在进行初次渲染时,会使用keyGenerator为数组中的每个元素生成一个唯一的key,并将key作为组件对象的标识。当数组发生变化导致ForEach
需要重新渲染时,ForEach
会再次使用keyGenerator为每个元素重新生成一遍key,然后ForEach
会检查新生成的key在上次渲染时是否已经存在,若存在,ForEach
就会认为这个key对应的数组元素没有发生变化,那它就会直接复用这个key所对应的组件对象;若不存在,ForEach
就会认为这个key对应的元素发生了变化,或者该元素为新增元素,此时,就会为该元素重新创建一个组件对象。
开发者可以通过keyGenerator函数自定义key的生成规则。如果开发者没有定义keyGenerator函数,则系统会使用默认的key生成函数,即
(item: any, index: number) => { return index + '__' + JSON.stringify(item); }
在某些情况下默认的key生成函数,会导致界面渲染效率低下,此时可考虑通过keyGenerator函数自定义生成逻辑,例如如下场景
状态变量数组定义如下
@State arr:string[] = ["zhangsan","lisi","wangwu"]
ForEach语句如下
Column(){
ForEach(this.arr,(item)=>{ Text(item) })
}
初次渲染时,每个元素对应的key依次为0__"zhagnsan"
、1__"lisi"
、2__"wangwu"
。若现有一个操作是向arr
数组头部插入新的元素,例如新元素为wanger,按照默认的key生成逻辑,插入新元素之后每个元素的key就会依次变为0__"wanger"
、1__"zhagnsan"
、2__"lisi"
、3__"wangwu"
,也就是所有元素的key都发生了变化,因此UI界面更新时需要为每个元素都重新创建组件对象,即便原有的元素没有发生变化也无法复用之前的组件,这样一来就导致了性能浪费。此时我们就可以考虑提供第三个参数,如下
Column(){
ForEach(this.arr, (item)=>{ Text(item) }, item => JSON.stringify(item))
}
- 点赞
- 收藏
- 关注作者
评论(0)