主页 > IT业界  > 

HarmonyOS学习--ArkTS开发语言入门

HarmonyOS学习--ArkTS开发语言入门

文章目录 一、编程语言介绍二、TypeScript基础类型1. 布尔值2. 数字3. 字符串4. 数组5. 元组6. 枚举7. unknown8. void9. null 和 undefined10. 联合类型 三、TypeScript基础知识条件语句if语句switch语句 函数定义有名函数和匿名函数可选参数剩余参数箭头函数 类1. 类的定义2. 继承 模块迭代器for..of 语句for..in 语句 四、ArkTS基础知识UI规范描述渲染控制状态管理组件生命周期函数: 五、ArkTS实践1. 声明式UI基本概念2. 自定义组件的组成3. 配置属性与布局4. 改变组件状态5. 循环渲染列表数据

一、编程语言介绍

ArkTS是HarmonyOS主力应用开发语言。它在TypeScript(简称TS)的基础上,匹配ArkUI框架,扩展了声明式UI、状态管理等相应的能力,让开发者以更简洁、更自然的方式开发跨端应用。

JavaScript是一种属于网络的高级脚本语言,已经被广泛应用开发,常用来为网页添加各式各样的动态功能,为用户提供更流畅美观的浏览效果。TypeScript是JavaScript的一个超集,它扩展了JavaScript的语法,通过在JavaScript的基础上添加静态类型定义构建而成,是一个开源的编程语言。ArkTS基于TypeScript语言,扩展了声明式UI、状态管理、并发任务等能力。

二、TypeScript基础类型 1. 布尔值 let isDone: boolean = false; 2. 数字

TypeScript里的所有数字都是浮点数,这些浮点数的类型是number。除了支持十进制,还支持二进制、八进制、十六进制

let decLiteral: number = 2023; let binaryLiteral: number = 0b11111100111; let octalLiteral: number = 0o3747; let hexLiteral: number = 0x7e7; console.log('decLiteral is' + decLiteral) // 结果都是2023 3. 字符串 let name: string = "Jacky"; 4. 数组

TypeSscript支持两种方式声明数组:

let list1: number[] = [1, 2, 3]; let list2: Array<number> = [1, 2, 3]; 5. 元组 let x: [string, number]; x = ['hello', 10] 6. 枚举 enum Color {Red, Green, Blue}; let c: Color = Color.Green; 7. unknown

有时候,我们会想要为那些在编程阶段还不清楚类型的变量指定一个类型。那么我们可以使用 unknown 类型来标记这些类型

let notSure: unknown = 4; notSure = 'maybe a string instead'; notSure = false; 8. void

当一个函数没有返回值时,通常会见到其返回值类型是void。

function test() void { console.log('This is function is void'); } 9. null 和 undefined

TypeScript里,undefined 和 null 两者各自有自己的类型分别叫做 undefined 和 unll。

let u: undefined = undefined; let n: null = null; 10. 联合类型

联合类型(Union Types)表示取值可以为多种类型中的一种。

let myFavoriteNumber: string | number;; myFavoriteNumber = 'seven'; myFavoriteNumber = 7; 三、TypeScript基础知识 条件语句 if语句 let num: number = 5; if (num > 0) { console.log('数字是正数'); } let num: number = 12; if (num % 2 == 0) { console.log('数字是偶数'); } else { console.log('数字是奇数'); } let num: number = 5; if (num > 0) { console.log(num + '是正数'); } else if (num < 0) { console.log(num + '是负数'); } else { console.log(num + '是0'); } switch语句 var grade: string = 'A'; switch(grade) { case 'A': { console.log('优'); break; } case 'B': { console.log('良'); break; } case 'C': { console.log('及格'); break; } case 'D': { console.log('不及格'); break; } default: { console.log('非法输入'); break; } } 函数定义 有名函数和匿名函数 // 有名函数:给变量设置为number类型 function add(x: number, y: number): number { return x + y; } // 匿名函数:给变量设置为number类型 let myAdd = function (x: number, y: number): number { return x + y; }; 可选参数 function buildName(firstName: string, lastName?: string) { if (lastName) return firstName + ' ' + lastName; else return firstName; } let result1 = buildName('Bob'); let result2 = buildName('Bob', 'Adams'); 剩余参数

剩余参数会被当做个数不限的可选参数。 可以一个都没有,同样也可以有任意个。 可以使用省略号( …)进行定义:

function getEmployeeName(firstName: string, ...restOfName: string[]) { return firstName + ' ' + restOfName.join(' '); } let employeeName = getEmployeeName('Joseph', 'Samuel', 'Lucas', 'MacKinzie'); 箭头函数

ES6版本的TypeScript提供了一个箭头函数,它是定义匿名函数的简写语法,用于函数表达式,它省略了function关键字。箭头函数的定义如下,其函数是一个语句块:

( [param1, parma2,…param n] )=> { // 代码块 }

其中,括号内是函数的入参,可以有0到多个参数,箭头后是函数的代码块。我们可以将这个箭头函数赋值给一个变量,如下所示:

let arrowFun = ( [param1, parma2,…param n] )=> { // 代码块 }

如果要主动调用这个箭头函数,可以按如下方法去调用:

arrowFun(param1, parma2,…param n) 类 1. 类的定义

TypeScript支持基于类的面向对象的编程方式,定义类的关键字为class,后面紧跟类名。类描述了所创 建的对象共同的属性和方法。 声明一个Person类,这个类有3个成员:一个是属性(包含name和age),一个是构造函数,一个是getPersonInfo方法,其定义如下所示。

class Person { private name: string private age: number constructor(name: string, age: number) { this.name = name; this.age = age; } public getPersonInfo(): string { return `My name is ${this.name} and age is ${this.age}`; } } let person1 = new Person('Jacky', 18); person1.getPersonInfo(); 2. 继承

继承就是子类继承父类的特征和行为,使得子类具有父类相同的行为。TypeScript中允许使用继承来扩展现有的类,对应的关键字为extends。

class Employee extends Person { private department: string constructor(name: string, age: number, department: string) { super(name, age); this.department = department; } public getEmployeeInfo(): string { return this.getPersonInfo() + ` and work in ${this.department}`; } } let person2 = new Employee('Tom', 28, 'HuaWei'); person2.getPersonInfo(); person2.getEmployeeInfo(); 模块

随着应用越来越大,通常要将代码拆分成多个文件,即所谓的模块(module)。模块可以相互加载,并可以使用特殊的指令 export 和 import 来交换功能,从另一个模块调用一个模块的函数。 两个模块之间的关系是通过在文件级别上使用 import 和 export 建立的。模块里面的变量、函数和类等在模块外部是不可见的,除非明确地使用 export 导出它们。类似地,我们必须通过 import 导入其他模块导出的变量、函数、类等。

导出 export class NewsData { title: string; content: string; imagesUrl: Array<NewsFile>; source: string; constructor(title: string, content: string, imagesUrl: Array<NewsFile>, source: string) { this.title = title; this.content = content; this.imagesUrl = imagesUrl; this.source = source; } } 导入 import { NewsData } from '../common/bean/NewsData'; 迭代器

当一个对象实现了Symbol.iterator属性时,我们认为它是可迭代的。一些内置的类型如Array,Map,Set,String,Int32Array,Uint32Array等都具有可迭代性。

for…of 语句 let someArray = [1, "string", false]; for (let entry of someArray) { console.log(entry); // 1, "string", false } for…in 语句 let list = [4, 5, 6]; for (let i in list) { console.log(i); // "0", "1", "2", } for (let i of list) { console.log(i); // "4", "5", "6" } 四、ArkTS基础知识 UI规范描述

ArkUI开发框架

ArkTS声明式开发范式

基本组成说明如下:

装饰器 用来装饰类、结构体、方法以及变量,赋予其特殊的含义,如上述示例中 @Entry 、 @Component 、 @State 都是装饰器。具体而言, @Component 表示这是个自定义组件; @Entry 则表示这是个入口组件; @State 表示组件中的状态变量,此状态变化会引起 UI 变更。

自定义组件 可复用的 UI 单元,可组合其它组件,如上述被 @Component 装饰的 struct Hello。

UI 描述 声明式的方式来描述 UI 的结构,如上述 build() 方法内部的代码块。

内置组件 框架中默认内置的基础和布局组件,可直接被开发者调用,比如示例中的 Column、Text、Divider、Button。

事件方法 用于添加组件对事件的响应逻辑,统一通过事件方法进行设置,如跟随在Button后面的onClick()。

属性方法 用于组件属性的配置,统一通过属性方法进行设置,如fontSize()、width()、height()、color() 等,可通过链式调用的方式设置多项属性。 从UI框架的需求角度,ArkTS在TS的类型系统的基础上,做了进一步的扩展:定义了各种装饰器、自定义组件和UI描述机制,再配合UI开发框架中的UI内置组件、事件方法、属性方法等共同构成了应用开发的主体。 在应用开发中,除了UI的结构化描述之外,还有一个重要的方面:状态管理。如上述示例中,用 @State 装饰过的变量 myText ,包含了一个基础的状态管理机制,即 myText 的值的变化会自动触发相应的 UI 变更 (Text组件)。ArkUI 中进一步提供了多维度的状态管理机制。和 UI 相关联的数据,不仅可以在组件内使用,还可以在不同组件层级间传递,比如父子组件之间,爷孙组件之间,也可以是全局范围内的传递,还可以是跨设备传递。另外,从数据的传递形式来看,可分为只读的单向传递和可变更的双向传递。开发者可以灵活的利用这些能力来实现数据和 UI 的联动。

总体而言,ArkUI开发框架通过扩展成熟语言、结合语法糖或者语言原生的元编程能力、以及UI组件、状态管理等方面设计了统一的UI开发范式,结合原生语言能力共同完成应用开发。这些构成了当前ArkTS基于TS的主要扩展。

渲染控制 条件渲染:使用if/else进行条件渲染。循环渲染:开发框架提供循环渲染(ForEach组件)来迭代数组,并为每个数组项创建相应的组件。 状态管理

组件状态管理装饰器用来管理组件中的状态,它们分别是:@State、@Prop、@Link。

@State装饰的变量是组件内部的状态数据,当这些状态数据被修改时,将会调用所在组件的build方法进行UI刷新。@Prop与@State有相同的语义,但初始化方式不同。@Prop装饰的变量必须使用其父组件提供的@State变量进行初始化,允许组件内部修改@Prop变量,但更改不会通知给父组件,即@Prop属于单向数据绑定。@Link装饰的变量可以和父组件的@State变量建立双向数据绑定,需要注意的是:@Link变量不能在组件内部进行初始化。@Builder装饰的方法用于定义组件的声明式UI描述,在一个自定义组件内快速生成多个布局内容。 @State、@Prop、@Link三者关系如图所示: 组件生命周期函数:

自定义组件的生命周期函数用于通知用户该自定义组件的生命周期,这些回调函数是私有的,在运行时由开发框架在特定的时间进行调用,不能从应用程序中手动调用这些回调函数。 自定义组件生命周期的简化图示:

五、ArkTS实践 1. 声明式UI基本概念

应用界面是由一个个页面组成,ArkTS是由ArkUI框架提供,用于以声明式开发范式开发界面的语言。

声明式UI构建页面的过程,其实是组合组件的过程,声明式UI的思想,主要体现在两个方面:

声明式描述:描述UI的呈现结果,而不关心过程状态驱动视图更新

类似苹果的SwiftUI中通过组合视图View,安卓Jetpack Compose中通过组合@Composable函数,ArkUI作为HarmonyOS应用开发的UI开发框架,其使用ArkTS语言构建自定义组件,通过组合自定义组件完成页面的构建。

2. 自定义组件的组成

ArkTS通过struct声明组件名,并通过@Component和@Entry装饰器,来构成一个自定义组件。 使用@Entry和@Component装饰的自定义组件作为页面的入口,会在页面加载时首先进行渲染。

@Entry @Component struct ToDoList {...}

使用@Component装饰的自定义组件,如ToDoItem这个自定义组件则对应如下内容,作为页面的组成部分。

@Component struct ToDoItem {...}

在自定义组件内需要使用build方法来进行UI描述。

@Entry @Component struct ToDoList ... build() { ... } }

build方法内可以容纳内置组件和其他自定义组件,如Column和Text都是内置组件,由ArkUI框架提供,ToDoItem为自定义组件,需要开发者使用ArkTS自行声明。

@Entry @Component struct ToDoList { ... build() { Column(...) { Text(...) ... ForEach(...{ TodoItem(...) },...) } ... } } 3. 配置属性与布局

自定义组件的组成使用基础组件和容器组件等内置组件进行组合。但有时内置组件的样式并不能满足我们的需求,ArkTS提供了属性方法用于描述界面的样式。

常量传递 例如使用fontSize(50)来配置字体大小。 Text('Hello World').fontSize(50) 变量传递 在组件内定义了相应的变量后,例如组件内部成员变量size,就可以使用this.size方式使用该变量。 Text('Hello World').fontSize(this.size) 链式调用 在配置多个属性时,ArkTS提供了链式调用的方式,通过’.'方式连续配置。 Text('Hello World') .fontSize(this.size) .width(100) .height(100) 表达式传递 属性中还可以传入普通表达式以及三目运算表达式。 Text('Hello World') .fontSize(this.size) .width(this.count + 100) .height(this.count % 2 === 0 ? 100 : 200) 内置枚举类型 除此之外,ArkTS中还提供了内置枚举类型,如Color,FontWeight等,例如设置fontColor改变字体颜色为红色,并私有fontWeight为加粗。 Text('Hello World') .fontSize(this.size) .width(this.count + 100) .height(this.count % 2 === 0 ? 100 : 200) .fontColor(Color.Red) .fontWeight(FontWeight.Bold)

对于有多种组件需要进行组合时,容器组件则是描述了这些组件应该如何排列的结果。

ArkUI中的布局容器有很多种,在不同的适用场合选择不同的布局容器实现,ArkTS使用容器组件采用花括号语法,内部放置UI描述。

这里介绍最基础的两个布局——列布局和行布局。 对于如下每一项的布局,两个元素为横向排列,选择Row布局 Row布局

Row() { Image($r('app.media.ic_default')) ... Text(this.content) ... } ...

类似下图所示的布局,整体都是从上往下纵向排列,适用的布局方式是Column列布局。 Column布局

Column() { Text($r('app.string.page_title')) ... ForEach(this.totalTasks,(item) =]]> { TodoItem({content:item}) },...) } 4. 改变组件状态

实际开发中由于交互,页面的内容可能需要产生变化,以每一个ToDoItem为例,其在完成时的状态与未完成时的展示效果是不一样的。

不同状态的视图

声明式UI的特点就是UI是随数据更改而自动刷新的,我们这里定义了一个类型为boolean的变量isComplete,其被@State装饰后,框架内建立了数据和视图之间的绑定,其值的改变影响UI的显示。

@State isComplete : boolean = false;

@State装饰器的作用

用圆圈和对勾这样两个图片,分别来表示该项是否完成,这部分涉及到内容的切换,需要使用条件渲染if / else语法来进行组件的显示与消失,当判断条件为真时,组件为已完成的状态,反之则为未完成。

if (this.isComplete) { Image($r('app.media.ic_ok')) .objectFit(ImageFit.Contain) .width($r('app.float.checkbox_width')) .height($r('app.float.checkbox_width')) .margin($r('app.float.checkbox_margin')) } else { Image($r('app.media.ic_default')) .objectFit(ImageFit.Contain) .width($r('app.float.checkbox_width')) .height($r('app.float.checkbox_width')) .margin($r('app.float.checkbox_margin')) }

由于两个Image的实现具有大量重复代码,ArkTS提供了@Builder装饰器,来修饰一个函数,快速生成布局内容,从而可以避免重复的UI描述内容。这里使用@Bulider声明了一个labelIcon的函数,参数为url,对应要传给Image的图片路径。

@Builder labelIcon(url) { Image(url) .objectFit(ImageFit.Contain) .width($r('app.float.checkbox_width')) .height($r('app.float.checkbox_width')) .margin($r('app.float.checkbox_margin')) }

使用时只需要使用this关键字访问@Builder装饰的函数名,即可快速创建布局。

if (this.isComplete) { this.labelIcon($r('app.media.ic_ok')) } else { this.labelIcon($r('app.media.ic_default')) }

为了让待办项带给用户的体验更符合已完成的效果,给内容的字体也增加了相应的样式变化,这里使用了三目运算符来根据状态变化修改其透明度和文字样式,如opacity是控制透明度,decoration是文字是否有划线。通过isComplete的值来控制其变化。

Text(this.content) ... .opacity(this.isComplete ? CommonConstants.OPACITY_COMPLETED : CommonConstants.OPACITY_DEFAULT) .decoration({ type: this.isComplete ? TextDecorationType.LineThrough : TextDecorationType.None })

最后,为了实现与用户交互的效果,在组件上添加了onClick点击事件,当用户点击该待办项时,数据isComplete的更改就能够触发UI的更新。

@Componentstruct ToDoItem { @State isComplete : boolean = false; @Builder labelIcon(icon) {...} ... build() { Row() { if (this.isComplete) { this.labelIcon($r('app.media.ic_ok')) } else { this.labelIcon($r('app.media.ic_default')) } ... } ... .onClick(() => { this.isComplete= !this.isComplete; }) } } 5. 循环渲染列表数据

刚刚只是完成了一个ToDoItem组件的开发,当我们有多条待办数据需要显示在页面时,就需要使用到ForEach循环渲染语法。

例如这里我们有五条待办数据需要展示在页面上。

total_Tasks: Array&lt;string]]> = ['早起晨练','准备早餐','阅读名著','学习ArkTS','看剧放松']

ForEach基本使用中,只需要了解要渲染的数据以及要生成的UI内容两个部分,例如这里要渲染的数组为以上的五条待办事项,要渲染的内容是ToDoItem这个自定义组件,也可以是其他内置组件。 ForEach基本使用

ToDoItem这个自定义组件中,每一个ToDoItem要显示的文本参数content需要外部传入,参数传递使用花括号的形式,用content接受数组内的内容项item。 最终完成的代码及其效果如下。

@Entry @Componentstruct ToDoList { ... build() { Row() { Column() { Text(...) ... ForEach(this.totalTasks,(item) => { TodoItem({content:item}) },...) } .width('100%') } .height('100%') } }

ToDoList页面

标签:

HarmonyOS学习--ArkTS开发语言入门由讯客互联IT业界栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“HarmonyOS学习--ArkTS开发语言入门