一节课上手鸿蒙开发

举报
王天一 发表于 2024/07/30 20:31:20 2024/07/30
【摘要】 本课程主要讲解基础鸿蒙应用开发,可适用于 1.HarmonyOS,适用于华为鸿蒙系统的手机、平板 2.OpenHarmony标准系统应用开发,应用于杂七杂八、各式各样的设备(银行自助设备、工业农业控制设备....)

一节课上手鸿蒙开发

作者:兰州大学信息科学与工程学院 钱浩莱、聂嘉一、叶清扬、王天一

注:本博客为兰州大学2024年2022级人工智能暑期学校暨华为开发者布道师活动的部分讲义

简介

只讲干货,不讲废话!!!

本课程主要讲解基础鸿蒙应用开发,可适用于

1.HarmonyOS,适用于华为鸿蒙系统的手机、平板

2.OpenHarmony标准系统应用开发,应用于杂七杂八、各式各样的设备(银行自助设备、工业农业控制设备…)

鸿蒙应用开发环境搭建

下载链接:

https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_package_901_9/ee/v3/HqJ-6O2FQny86xtk_dg9HQ/devecostudio-windows-4.1.0.400.zip?HW-CC-KV=V1&HW-CC-Date=20240409T033730Z&HW-CC-Expire=315360000&HW-CC-Sign=BFA444BC43A041331E695AE2CFA9035A957AF107E06C97E793FD3D31D7096A0D

安装教程:

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%')  //设置高度占比
  } 
}

image.png

text、image组件

text组件,就是显示文字

用法:

Text("显示的字符串")

Text(字符串变量名)

相关案例见: demos/TextDemo

image.png

image组件,就是显示图片

相关案例见: demos/ImageDemo

用法:

(1)Image(图片文件路径) (相对于ets目录的路径)

image.png

(2)Image($r('app.media.tiger'))

把图片放在 "工程名\entry\src\main\resources\base\media"目录下,这样用法不要加后缀名

image.png

(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提供了很多的内置组件,例如:TextButtonImage等等;并且ArkTS还支持自定义组件,让开发者可根据具体需求自定义组件中的内容。

当然,实现按钮不一定需要用按钮组件,其他组件加上点击事件也具有按钮功能

相关案例见: demos/buttonDemo

image.png

TextInput组件,就是一个输入框

用法如下,

TextInput({placeholder:"输入提示"}).onChange((value)=>{
  输入值改变时,执行的函数,value为输入框中输入的值
})

相关案例见:demos/TextInputDemo

image.png

线性布局

概述

线性布局(LinearLayout)是开发中最常用的布局,可通过容器组件ColumnRow构建,其子组件会在垂直或者水平方向上进行线性排列,具体效果如下图所示

| img
| image.png

说明

ColumnRow容器均有两个轴线,分别是主轴交叉轴

  • 主轴:线性布局容器在布局方向上的轴线,**Row**容器主轴为横向**Column**容器主轴为纵向
  • 交叉轴:垂直于主轴方向的轴线。**Row**容器交叉轴为纵向**Column**容器交叉轴为横向

参数

ColumnRow容器的参数类型为{space?: string | number},开发者可通过space属性调整子元素在主轴方向上的间距,效果如下

| image.png|image.png|
| | |

相关案例见:demos/LinearLayoutDemo/SpacePage.ets

常用属性

子元素沿主轴方向的排列方式

子元素沿主轴方向的排列方式可以通过justifyContent()方法进行设置,其参数类型为枚举类型FlexAlign,可选的枚举值有

名称 Start Center End SpaceBetween SpaceAround SpaceEvenly
描述 头部对齐 居中对齐 尾部对齐 均匀分布,首尾两项两端对齐,中间元素等间距分布 均匀分布,所有子元素两侧都留有相同的空间 均匀分布,所有子元素之间以及首尾两元素到两端的距离都相等
效果(以Column容器为例) image.png image.png image.png image.png image.png image.png

相关案例见:demos/LinearLayoutDemo/JustifyContent.ets

子元素沿交叉轴方向的对齐方式

子元素沿交叉轴方向的对齐方式可以通过alignItems()方法进行设置,其参数类型,对于Column容器来讲是HorizontalAlign,对于Row容器来讲是VerticalAlign,两者都是枚举类型,可选择枚举值也都相同,具体内容如下

名称 Start Center End
描述 头部对齐 居中对齐 尾部对齐
效果(以Column容器为例) image.png image.png image.png

相关案例见:demos/LinearLayoutDemo/AlignItemsPage.ets

自定义组件

在鸿蒙开发中,组件是构成界面的最小单元,我们所看到的界面,都是由众多组件组合而成的,所以编写界面其实就是组合组件的过程,ArkTS提供了很多的内置组件,例如:TextButtonImage等等;并且ArkTS还支持自定义组件,让开发者可根据具体需求自定义组件中的内容。

除去系统预置的组件外,ArkTS 还支持自定义组件。使用自定义组件,可使代码的结构更加清晰,并且能提高代码的复用性。

自定义组件的语法如下图所示

image.png

各部分语法说明如下:

  • **struct**关键字

structArkTS新增的用于自定义组件或者自定义弹窗的关键字。其声明的数据结构和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会自动完成页面的注册。

image.png

第二步:导入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)) 
}
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。