当前位置:   article > 正文

【零基础学鸿蒙】ArkTS开发语言介绍

【零基础学鸿蒙】ArkTS开发语言介绍

在之前的教学中,我们学习了下载安装DevEco Studio等相关知识。今天开始讲ArkTS

1.1 TypeScrip快速入门

学习TypeScript对于HarmonyOS应用开发至关重要。在HarmonyOS中,主力编程语言为ArKTS,它是基于TypeScript的一种语言,其通过与ArkUI框架的匹配,拓展了声明式UI和状态管理等能力,使开发者能够以更简洁自然的方式开发跨端应用。TypeScript本身是JavaScript的超集,通过引入静态类型定义等特性,提高了代码的可维护性和可读性,有助于在编码阶段检测潜在错误,提高开发效率另外,学习TypeScript还为处理HarmonyOS应用中的UI和应用状态提供了更强大的支持,在并发任务方面也有相应的扩展。为了更好地对HarmonyOS进行开发需要掌握TypeScript语言,本接我们重点介绍TypeScript语言。
鸿蒙学习小助手V【hmos19】解答、咨询、项目实战

1.1.1 编程语言介绍

ArkTS是HarmonyOS优选的主力应用开发语言。它在TypeScript(简称TS)的基础上,匹配ArkUI框架,扩展了声明式UI、状态管理等相应的能力,让开发者以更简洁、更自然的方式开发跨端应用。要了解什么是ArkTS,我们首先要了解下ArkTS、TypeScript和JavaScript之间的关系:

图片

lJavaScript是一种属于网络的高级脚本语言,已经被广泛用于Web应用开发,常用来为网页添加各式各样的动态功能,为用户提供更流畅美观的浏览效果。

lTypeScript 是 JavaScript 的一个超集,它扩展了 JavaScript 的语法,通过在JavaScript的基础上添加静态类型定义构建而成,是一个开源的编程语言。

lArkTS兼容TypeScript语言,拓展了声明式UI、状态管理、并发任务等能力。

在学习ArkTS声明式的相关语法之前,我们首先学习下TypeScript的基础语法。

1.1.2 基础类型

TypeScript支持一些基础的数据类型,如布尔型、数组、字符串等,下文举例几个较为常用的数据类型,我们来了解下他们的基本使用。

Ø布尔值

TypeScript中可以使用boolean来表示这个变量是布尔值,可以赋值为true或者false。例如我们这里可以设置IsDone为False来表示未完成。

let isDone: boolean = false;
  • 1

Ø数字

TypeScript里的所有数字都是浮点数,这些浮点数的类型是 number。除了支持十进制,还支持二进制、八进制、十六进制。如下我们用十进制、二进制、八进制和十六进制分别定义了2023,当把数据通过日志方式打印出来,结果都会转换为十进制,也都是2023。

let decLiteral: number = 2023;

let binaryLiteral: number = 0b11111100111;

let octalLiteral: number = 0o3747;

let hexLiteral: number = 0x7e7;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

Ø字符串

TypeScript里使用 string表示文本数据类型, 可以使用双引号( ")或单引号(')表示字符串。例如我们这里定义Name是一个字符串类型,其数值我们可以用双引号或者单引号包裹起来。

let name: string = "Jacky";

name = "Tom";

name = 'Mick';
  • 1
  • 2
  • 3
  • 4
  • 5

Ø数组

TypeScrip有两种方式可以定义数组。第一种,可以在元素类型后面接上 [],表示由此类型元素组成的一个数组。

let list: number[] = [1, 2, 3];
  • 1

第二种方式是使用数组泛型,Array<元素类型>。

let list: Array<number> = [1, 2, 3];
  • 1

Ø元组

元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同。 比如,你可以定义一对值分别为 string和number类型的元组。

例如这里我们定义了一个X元组,类型为String和Number。第一行的赋值和我们元组定义的顺序是一致的,这种是正确的。第二行先赋值Number后赋值String,这种赋值的顺序和我们定义的不一致,所以是错误的。

let x: [string, number];

x = ['hello', 10]; // OK

x = [10, 'hello']; // Error
  • 1
  • 2
  • 3
  • 4
  • 5

Ø枚举

enum类型是对JavaScript标准数据类型的一个补充,使用枚举类型可以为一组数值赋予友好的名字。例如我们这里定义Color为Red, Green和Blue,到时候就可以使用Color.Green来定义颜色。

enum Color {Red, Green, Blue};

let c: Color = Color.Green;
  • 1
  • 2
  • 3

ØUnknown

有时候,我们会想要为那些在编程阶段还不清楚类型的变量指定一个类型。这种情况下,我们不希望类型检查器对这些值进行检查而是直接让它们通过编译阶段的检查。那么我们可以使用unknown类型来标记这些变量。

如下案例中,这里的Not Sure定义为Unknown后,我们可以赋值为Number类型,也可以赋值为String类型,还可以赋值为false类型。

let notSure: unknown = 4;

notSure = 'maybe a string instead';

notSure = false;
  • 1
  • 2
  • 3
  • 4
  • 5

ØVoid

当一个函数没有返回值时,你通常会见到其返回值类型是 void。如下的test方法,其返回类型就是Void。

function test(): void {

   console.log('This is function is void');

}
  • 1
  • 2
  • 3
  • 4
  • 5

ØNull 和 Undefined

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

let u: undefined = undefined;

let n: null = null;
  • 1
  • 2
  • 3

Ø联合类型

联合类型(Union Types)表示取值可以为多种类型中的一种。例如我们这里定义MyFavoriteNumber为联合类型,其取值可以是String或者Number,我们可以给其赋值为字符串7,也可以给其赋值为Number类型7。联合类型在日常的使用过程中用的比较多,大家要掌握这种定义方式。

let myFavoriteNumber: string | number;

myFavoriteNumber = 'seven';

myFavoriteNumber = 7;
  • 1
  • 2
  • 3
  • 4
  • 5

1.1.3 条件语句

条件语句用于基于不同的条件来执行不同的动作。TypeScript 条件语句是通过一条或多条语句的执行结果(True 或 False)来决定执行的代码块。

Øif 语句

TypeScript if 语句由一个布尔表达式后跟一个或多个语句组成。例如,如下代码中是一个If语句,定义的Number为5,判断的条件是Number大于0,程序满足这个条件会输出数字为正数。

var num:number = 5

if (num > 0) {

   console.log('数字是正数')

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

Øif…else 语句

一个 if 语句后可跟一个可选的 else 语句,else 语句在布尔表达式为 false 时执行。如下代码中声明一个If-else语句,定义的Number是12,符合Number对2取余等于0的条件,所以输出为偶数。

var num:number = 12;

if (num % 2==0) {

    console.log('偶数');

} else {

    console.log('奇数');

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

Øif…else if…else 语句

if…else if…else 语句在执行多个判断条件的时候很有用。如下代码中是一个If-else语句,定义的Number为0,满足最后的else条件,所以输出为0。

var num:number = 0

if(num > 0) {

    console.log(num+' 是正数')

} else if(num < 0) {

    console.log(num+' 是负数')

} else {

    console.log(num+' 为0')

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

Øswitch…case 语句

除了可以通过If-else语句进行条件判断外,还可以通过Switch-case语句进行条件判断。一个 switch 语句允许测试一个变量等于多个值时的情况。每个值称为一个 case,且被测试的变量会对每个 switch case 进行检查。

如下代码中我们有4个Case条件,分别是A输出日志优,B输出日志良,C输出日志及格,D输出日志不及格,最后还有一个default条件,当输入的字符不在ABCD中则表示非法输入,最后我们定义的Grade为A,所以这个代码打印的日志为优。

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;              

    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

1.1.4 函数

函数是一组一起执行一个任务的语句,函数声明要告诉编译器函数的名称、返回类型和参数。TypeScript可以创建有名字的函数和匿名函数,其创建方法如下:

// 有名函数

function add(x, y) {

  return x + y;

}

 

// 匿名函数

let myAdd = function (x, y) {

  return x + y;

};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

Ø为函数定义类型

为了确保输入输出的准确性,我们可以为上面那个函数添加类型:

// 有名函数:给变量设置为number类型

function add(x: number, y: number): number {

  return x + y;

}

 

// 匿名函数:给变量设置为number类型

let myAdd = function (x: number, y: number): number {

  return x + y;

};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

以上函数的名称叫做Add,实现的是两个数值的累加,参数是X和Y两个number类型的数字,返回值是X+Y的结果。其返回的类型也是number类型,上面一个函数是有名函数,下面一个函数是匿名函数,匿名函数没有函数名,但其作用是一样的。

Ø可选参数

在TypeScript里我们可以在参数名旁使用 ?实现可选参数的功能。比如,我们想让lastName是可选的。使用了可选参数后,我们在调用函数的时候就可以传入一个参数或者两个参数,如Result1和Result2中的代码所示:

function buildName(firstName: string, lastName?: string) {

    if (lastName)

        return firstName + ' ' + lastName;

    else

        return firstName;

}

 

let result1 = buildName('Bob');

let result2 = buildName('Bob', 'Adams');
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

Ø剩余参数

函数的入参除了可以使用可选参数外,还可以使用剩余参数。剩余参数会被当做个数不限的可选参数,可以一个都没有,同样也可以有任意个。 可以使用省略号( …)进行定义。如下代码中,我们调用getEmployeeName方法时,可以只传入firstName,也就是Joseph,不传入剩余参数,也可以传入多个剩余参数:Samuel,Lucas,MacKinzie等。

function getEmployeeName(firstName: string, ...restOfName: string[]) {

  return firstName + ' ' + restOfName.join(' ');

}

 

let employeeName = getEmployeeName('Joseph', 'Samuel', 'Lucas', 'MacKinzie');
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

Ø箭头函数

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

( [param1, parma2,…param n] )=> {

    // 代码块

}
  • 1
  • 2
  • 3
  • 4
  • 5

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

let arrowFun = ( [param1, parma2,…param n] )=> {

    // 代码块

}
  • 1
  • 2
  • 3
  • 4
  • 5

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

arrowFun(param1, parma2,…param n)
  • 1

接下来我们看看如何将我们熟悉的函数定义方式转换为箭头函数。我们可以定义一个判断正负数的函数,如下:

function testNumber(num: number) {

  if (num > 0) {

    console.log(num + ' 是正数');

  } else if (num < 0) {

    console.log(num + ' 是负数');

  } else {

    console.log(num + ' 为0');

  }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

其调用方法如下:

testNumber(1) //输出日志:1 是正数

如果将这个函数定义为箭头函数,定义如下所示:

let testArrowFun = (num: number) => {

  if (num > 0) {

    console.log(num + ' 是正数');

  } else if (num < 0) {

    console.log(num + ' 是负数');

  } else {

    console.log(num + ' 为0');

  }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

其调用方法如下:

testArrowFun(-1) //输出日志:-1 是负数

后面,我们在学习HarmonyOS应用开发时会经常用到箭头函数。例如,给一个按钮添加点击事件,其中onClick事件中的函数就是箭头函数。

Button("Click Now")

  .onClick(() => {

    console.info("Button is click")

  })
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

1.1.5 类

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}`;

  }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

通过上面的Person类,我们可以定义一个人物Jacky并获取他的基本信息,其定义如下,我们可以使用new方法,传入person的姓名和年龄,创建为person1对象,person1可以调用其中的公有属性的方法,也就是getpersoninfo方法,这个是一个最简单的类的定义和调用。当然类里面还有很多的知识,比如我们可以通过修改修饰符,private public等来控制属性和方法的访问权限,这些知识大家可以参考TS的相关文档进行自行学习。

let person1 = new Person('Jacky', 18);

person1.getPersonInfo();
  • 1
  • 2
  • 3

Ø继承

继承就是子类继承父类的特征和行为,使得子类具有父类相同的行为。TypeScript中允许使用继承来扩展现有的类,对应的关键字为extends。如下案例中,我们定义employee是继承于person的employee叫person新增了一个属性department,我们可以这样去定义它的构造方法,通过super关键字实际上就调用了person中的构造方法,初始化name和age,并在构造方法中初始化好了department,employee有个公有方法,getemployeeinfo获取雇员的信息,其中调用getpersoninfo来获取雇员的姓名、年龄信息。

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}`;

  }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

通过上面的Employee类,我们可以定义一个人物Tom,这里可以获取他的基本信息,也可以获取他的雇员信息,其定义如下:

let person2 = new Employee('Tom', 28, 'HuaWei');

person2.getPersonInfo();

person2.getEmployeeInfo();
  • 1
  • 2
  • 3
  • 4
  • 5

在TypeScript中,有public、private、protected修饰符,其功能和具体使用场景大家可以参考TypeScript的相关学习资料,进行拓展学习。

1.1.6 模块

随着应用越来越大,通常要将代码拆分成多个文件,即所谓的模块(module)。模块可以相互加载,并可以使用特殊的指令 export 和 import 来交换功能,从另一个模块调用一个模块的函数。

两个模块之间的关系是通过在文件级别上使用 import 和 export 建立的。模块里面的变量、函数和类等在模块外部是不可见的,除非明确地使用 export 导出它们。类似地,我们必须通过 import 导入其他模块导出的变量、函数、类等。

Ø导出

任何声明(比如变量,函数,类,类型别名或接口)都能够通过添加export关键字来导出,例如我们要把NewsData这个类导出,代码示意如下:

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;

  }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

Ø导入

模块的导入操作与导出一样简单。 可以使用以下 import形式之一来导入其它模块中的导出内容。

import { NewsData } from '../common/bean/NewsData';
  • 1

以上案例中,我们在一个文件中定义了一个类news data,我们要在其他文件中引用这个类,首先就需要在这个类的前面加一个修饰符export,之后我们可以利用import来导入这个类,这个类的具体路径是填写在form后面的。export进来后,我们就可以在这个模块中引用其他模块中定义的NewsData。

1.1.7 可迭代对象

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

Øfor…of 语句

for…of会遍历可迭代的对象,调用对象上的Symbol.iterator方法。下面是在数组上使用for…of的简单例子,如这里定了一个someArray 数组,使用for-of语句进行循环遍历,可以打印这个数组中的元素。

let someArray = [1, "string", false];

 

for (let entry of someArray) {

    console.log(entry); // 1, "string", false

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

Øfor…of vs. for…in 语句

for…of和for…in均可迭代一个列表,但是用于迭代的值却不同:for…in迭代的是对象的键,而for…of则迭代的是对象的值。如下,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"

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

1.1.8 DevEco Studio中配置TypeScript

配置node.js的环境变量:

图片

安装 typescript:

npm install -g typescript
  • 1

安装完成后我们可以使用tsc 命令来执行 TypeScript 的相关代码,以下是查看版本号:

$ tsc -v

Version 5.3.2
  • 1
  • 2
  • 3

1.1 初识ArkTs语言

ArkTS是HarmonyOS优选的主力应用开发语言。ArkTS围绕应用开发在TypeScript(简称TS)生态基础上做了进一步扩展,继承了TS的所有特性,是TS的超集。因此,在学习ArkTS语言之前,建议开发者具备TS语言开发能力。

当前,ArkTS在TS的基础上主要扩展了如下能力:

l基本语法:ArkTS定义了声明式UI描述、自定义组件和动态扩展UI元素的能力,再配合ArkUI开发框架中的系统组件及其相关的事件方法、属性方法等共同构成了UI开发的主体。

l状态管理:ArkTS提供了多维度的状态管理机制。在UI开发框架中,与UI相关联的数据可以在组件内使用,也可以在不同组件层级间传递,比如父子组件之间、爷孙组件之间,还可以在应用全局范围内传递或跨设备传递。另外,从数据的传递形式来看,可分为只读的单向传递和可变更的双向传递。开发者可以灵活的利用这些能力来实现数据和UI的联动。

l渲染控制:ArkTS提供了渲染控制的能力。条件渲染可根据应用的不同状态,渲染对应状态下的UI内容。循环渲染可从数据源中迭代获取数据,并在每次迭代过程中创建相应的组件。数据懒加载从数据源中按需迭代数据,并在每次迭代过程中创建相应的组件。

未来,ArkTS会结合应用开发/运行的需求持续演进,逐步提供并行和并发能力增强、系统类型增强、分布式开发范式等更多特性。

1.2 ArkTS基本语法

1.2.1 基本语法概述

在初步了解了ArkTS语言之后,我们以一个具体的示例来说明ArkTS的基本组成。该案例中当开发者点击按钮时,文本内容从“Hello World”变为“Hello ArkUI”,创建步骤如下。

1)打开 DevEvo Studio开发工具,新建项目

项目创建完成,进入该项目等待项目初始化完成即可:

2)在Index.ets中写入如下代码

@Entry
@Component
struct Hello {
  @State myText: string = 'World'

  build() {
    Column(){
      Text(`Hello ${this.myText}`)
        .fontSize(50)
      Divider()
      Button('Click me')
        .onClick(()=>{
          this.myText='ArkUI'
        })
        .height(50)
        .width(100)
        .margin({top:20})
    }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

对以上代码详细解释如下:

//@Entry装饰的自定义组件将作为UI页面的入口。在单个UI页面中,最多可以使用@Entry装饰一个自定义组件。
@Entry
/**
 * @Component是一种装饰器,代表自定义组件,用@Component 装饰的 struct Hello 代表一个自定义的结构体,名字是Hello,是可重用的UI单元,可以与其他组件组合。
 */
@Component
struct Hello {
  //@State 是一种装饰器,被它装饰的变量 myText 值发生改变时,会触发该变量所对应的自定义组件 Hello 的 UI 界面进行自动刷新。
  @State myText: string = 'World'

  //build 方法中的代码块表示UI描述,以声明式的方式描述UI结构。
  build() {
    //Column 是内置组件,表示设置一列
    Column(){
      //设置文本及内容
      Text(`Hello ${this.myText}`)
        .fontSize(50)//设置文本大小
      Divider() //Divider 提供分隔器组件,分隔不同内容块/内容元素。
      //设置按钮
      Button('Click me')
        //设置按钮点击事件,点击按钮时将 myText 由 World 改变成 ArkUI
        .onClick(()=>{
          this.myText='ArkUI'
        })
        .height(50) //设置按钮高度
        .width(100) //设置按钮宽度
        .margin({top:20}) //设置按钮外边距
    }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

3)打开预览,验证组件功能

当点击“Click me”按钮时,“Hello World”变换成“Hello ArkUI”。

在以上示例中,ArkTS的基本组成如下所示。

l装饰器: 用于装饰类、结构、方法以及变量,并赋予其特殊的含义。如上述示例中@Entry、@Component和@State都是装饰器,@Component表示自定义组件,@Entry表示该自定义组件为入口组件,@State表示组件中的状态变量,状态变量变化会触发UI刷新。

lUI描述:以声明式的方式来描述UI的结构,例如build()方法中的代码块。

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

l系统组件:ArkUI框架中默认内置的基础和容器组件,可直接被开发者调用,比如示例中的Column、Text、Divider、Button。

l属性方法:组件可以通过链式调用配置多项属性,如fontSize()、width()、height()、backgroundColor()等。

l事件方法:组件可以通过链式调用设置多个事件的响应逻辑,如跟随在Button后面的onClick()。

系统组件、属性方法、事件方法具体使用可参考基于ArkTS的声明式开发范式。除此之外,ArkTS扩展了多种语法范式来使开发更加便捷:

l@Builder/@BuilderParam:特殊的封装UI描述的方法,细粒度的封装和复用UI描述。

l@Extend/@Style:扩展内置组件和封装属性样式,更灵活地组合内置组件。

lstateStyles:多态样式,可以依据组件的内部状态的不同,设置不同样式。

1.2.2 声明式UI概述

ArkTS以声明方式组合和扩展组件来描述应用程序的UI,同时还提供了基本的属性、事件和子组件配置方法,帮助开发者实现应用交互逻辑。

1.2.2.1 创建组件

根据组件构造方法的不同,创建组件包含有参数和无参数两种方式。创建组件时不需要new运算符。

l无参数

如果组件的接口定义没有包含必选构造参数,则组件后面的“()”不需要配置任何内容。例如,Divider组件不包含构造参数:

Column() {

  Text('item 1')

  Divider()

  Text('item 2')

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

示例演示:

@Entry
@Component
struct UITest {
  build() {
    Column() {
      Text('item 1')
      Divider()
      Text('item 2')
    }
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

预览如下:

l有参数

如果组件的接口定义包含构造参数,则在组件后面的“()”配置相应参数。

a.Image组件的必选参数src。

Image('https://xyz/test.jpg')
  • 1

b.Text组件的非必选参数content。

// string类型的参数

Text('test')

// $r形式引入应用资源,可应用于多语言场景

Text($r('app.string.title_value'))

// 无参数形式

Text()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

c.变量或表达式也可以用于参数赋值,其中表达式返回的结果类型必须满足参数类型要求。

Image(this.imagePath)

Image('https://' + this.imageUrl)

Text(`count: ${this.count}`)
  • 1
  • 2
  • 3
  • 4
  • 5

示例演示:

@Entry
@Component
struct UITest {
  build() {
    Column() {
      Image('https://img0.baidu.com/it/u=110176915,621401482&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=665')
        .height(500)
      Text('美女')
    }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

预览如下:

1.2.2.2 配置属性

属性方法以“.”链式调用的方式配置系统组件的样式和其他属性,建议每个属性方法单独写一行。

l配置Text组件的字体大小。

Text('test')

  .fontSize(12)
  • 1
  • 2
  • 3

l配置组件的多个属性。

Image('test.jpg')

  .alt('error.jpg')    

  .width(100)    

  .height(100)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

l除了直接传递常量参数外,还可以传递变量或表达式。

Text('hello')

  .fontSize(this.size)

Image('test.jpg')

  .width(this.count % 2 === 0 ? 100 : 200)    

  .height(this.offset + 100)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

l对于系统组件,ArkUI还为其属性预定义了一些枚举类型供开发者调用,枚举类型可以作为参数传递,但必须满足参数类型要求。

例如,可以按以下方式配置Text组件的颜色和字体样式。

Text('hello')

  .fontSize(20)

  .fontColor(Color.Red)

  .fontWeight(FontWeight.Bold)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

示例:

@Entry
@Component
struct UITest {
  textSize: number = 50;
  count:number = 2;
  imageOffset:number = 700;

  build() {
    Column(){
      Text("Hello ArkTS")
        .fontSize(this.textSize)
        .fontColor(Color.Red)
        .fontWeight(FontWeight.Bold)

      Image('https://img0.baidu.com/it/u=110176915,621401482&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=665')
        .width(this.count%2 === 0?500:200)
        .height(this.imageOffset + 100)
    }

  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

预览如下:

鸿蒙学习小助手V【hmos19】解答、咨询、项目实战

1.2.2.3 配置事件

事件方法以“.”链式调用的方式配置系统组件支持的事件,建议每个事件方法单独写一行。

l使用箭头函数配置组件的事件方法。

Button('Click me')

  .onClick(() => {

    this.myText = 'ArkUI';

  })
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

l使用匿名函数表达式配置组件的事件方法,要求使用bind,以确保函数体中的this指向当前组件。

Button('add counter')

  .onClick(function(){

    this.counter += 2;

  }.bind(this))

l使用组件的成员函数配置组件的事件方法。

myClickHandler(): void {

  this.counter += 2;

}

...

Button('add counter')

  .onClick(this.myClickHandler.bind(this))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

示例:

@Entry
@Component
struct UITest {
  @State textSize: number = 20;

  myClickHandler(): void {
    this.textSize += 10;
  }

  build() {
    Column() {
      Text("Hello ArkTS")
        .fontSize(this.textSize)
        .fontColor(Color.Red)
        .fontWeight(FontWeight.Bold)
      Divider()
      Button("增大字体")
        .height(50)
        .width(100)
        .margin(20)
        .onClick(this.myClickHandler.bind(this))
    }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

预览如下,每次点击“增大字体”按钮后,“Hello ArkTS”都会变大。

1.2.2.4 配置子组件

如果组件支持子组件配置,则需在尾随闭包"{…}"中为组件添加子组件的UI描述。Column、Row、Stack、Grid、List等组件都是容器组件。

l以下是简单的Column组件配置子组件的示例。

Column() {

Text(‘Hello’)

.fontSize(100)
  • 1

Divider()

Text(this.myText)

.fontSize(100)

.fontColor(Color.Red)
  • 1
  • 2
  • 3

}

l容器组件均支持子组件配置,可以实现相对复杂的多级嵌套。

Column() {

Text(‘Hello’)

.fontSize(100)
  • 1

Divider()

Text(this.myText)

.fontSize(100)

.fontColor(Color.Red)
  • 1
  • 2
  • 3

}

1.2.3 基础组件-Text

Text组件是可以显示一段文本的组件。该组件从API Version 7开始支持,从API version 9开始,该接口支持在ArkTS卡片中使用。

1.2.3.1 用法
该组件使用方式如下:

Text(content?: string | Resource)
  • 1

以上参数解释如下:

在这里插入图片描述
Text组件支持很多通用属性,如:width、height等,还支持如下属性:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
鸿蒙学习小助手V【hmos19】解答、咨询、项目实战在这里插入图片描述

1.2.3.2 示例

以下代码定义了一个名为 TextExample1 的组件,用于展示不同文本样式的效果,包括文本对齐、文本溢出处理和行高设置。

@Entry  // 使用 @Entry 装饰器标识这是一个入口组件。
@Component  // 使用 @Component 装饰器定义一个新组件。
struct TextExample1 {  // 定义名为 TextExample1 的结构体,代表这个组件。

  build() {  // 定义 build 方法来构建UI。
    Flex({  // 创建一个弹性布局容器。
      direction: FlexDirection.Column,  // 设置布局方向为垂直列。
      alignItems: ItemAlign.Start,  // 设置子项沿主轴的起始位置对齐。
      justifyContent: FlexAlign.SpaceBetween  // 设置子项间距均匀分布。
    }) {
      // 文本水平方向对齐方式设置
      // 单行文本
      Text('textAlign').fontSize(9).fontColor(0xCCCCCC)  // 创建一个文本组件,说明接下来的文本对齐设置。

      Text('TextAlign set to Center.')  // 创建一个文本组件,文本居中对齐。
        .textAlign(TextAlign.Center)  // 设置文本对齐方式为居中。
        .fontSize(12)  // 设置字体大小为12。
        .border({ width: 1 })  // 设置边框宽度为1。
        .padding(10)  // 设置内边距为10。
        .width('100%')  // 设置宽度为100%。

      Text('TextAlign set to Start.')  // 创建一个文本组件,文本起始对齐。
        .textAlign(TextAlign.Start)  // 设置文本对齐方式为起始对齐。
        .fontSize(12)  // 设置字体大小为12。
        .border({ width: 1 })  // 设置边框宽度为1。
        .padding(10)  // 设置内边距为10。
        .width('100%')  // 设置宽度为100%。

      Text('TextAlign set to End.')  // 创建一个文本组件,文本结束对齐。
        .textAlign(TextAlign.End)  // 设置文本对齐方式为结束对齐。
        .fontSize(12)  // 设置字体大小为12。
        .border({ width: 1 })  // 设置边框宽度为1。
        .padding(10)  // 设置内边距为10。
        .width('100%')  // 设置宽度为100%。

      // 多行文本
      Text('This is the text content with textAlign set to Center.')  // 创建一个多行文本组件,文本居中对齐。
        .textAlign(TextAlign.Center)  // 设置文本对齐方式为居中。
        .fontSize(12)  // 设置字体大小为12。
        .border({ width: 1 })  // 设置边框宽度为1。
        .padding(10)  // 设置内边距为10。
        .width('100%')  // 设置宽度为100%。

      Text('This is the text content with textAlign set to Start.')  // 创建一个多行文本组件,文本起始对齐。
        .textAlign(TextAlign.Start)  // 设置文本对齐方式为起始对齐。
        .fontSize(12)  // 设置字体大小为12。
        .border({ width: 1 })  // 设置边框宽度为1。
        .padding(10)  // 设置内边距为10。
        .width('100%')  // 设置宽度为100%。

      Text('This is the text content with textAlign set to End.')  // 创建一个多行文本组件,文本结束对齐。
        .textAlign(TextAlign.End)  // 设置文本对齐方式为结束对齐。
        .fontSize(12)  // 设置字体大小为12。
        .border({ width: 1 })  // 设置边框宽度为1。
        .padding(10)  // 设置内边距为10。
        .width('100%')  // 设置宽度为100%。

      // 文本超长时显示方式
      Text('TextOverflow+maxLines').fontSize(9).fontColor(0xCCCCCC)  // 创建一个文本组件,说明接下来的文本溢出设置。

      // 超出maxLines截断内容展示
      Text('This is the setting of textOverflow to Clip text content This is the setting of textOverflow to None text content. This is the setting of textOverflow to Clip text content This is the setting of textOverflow to None text content.')
        .textOverflow({ overflow: TextOverflow.Clip })  // 设置文本溢出方式为剪裁(Clip)。
        .maxLines(1)  // 设置最大行数为1。
        .fontSize(12)  // 设置字体大小为12。
        .border({ width: 1 })  // 设置边框宽度为1。
        .padding(10)  // 设置内边距为10。

      // 超出maxLines展示省略号
      Text('This is set textOverflow to Ellipsis text content This is set textOverflow to Ellipsis text content.'.split('')
        .join('\u200B'))
        .textOverflow({ overflow: TextOverflow.Ellipsis })  // 设置文本溢出方式为省略号(Ellipsis)。
        .maxLines(1)  // 设置最大行数为1。
        .fontSize(12)  // 设置字体大小为12。
        .border({ width: 1 })  // 设置边框宽度为1。
        .padding(10)  // 设置内边距为10。

      Text('lineHeight').fontSize(9).fontColor(0xCCCCCC)  // 创建一个文本组件,说明接下来的行高设置。

      // 设置文本的行高
      Text('This is the text with the line height set. This is the text with the line height set.')
        .fontSize(12)  // 设置字体大小为12。
        .border({ width: 1 })  // 设置边框宽度为1。
        .padding(10)  // 设置内边距为10。
      Text('This is the text with the line height set. This is the text with the line height set.')
        .fontSize(12)  // 设置字体大小为12。
        .border({ width: 1 })  // 设置边框宽度为1。
        .padding(10)  // 设置内边距为10。
        .lineHeight(20)  // 设置行高为20。
    }.height(600).width(350).padding({ left: 35, right: 35, top: 35 })  // 设置容器的高度、宽度和内边距。
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92

以上代码预览如下:

1.2.4 容器组件-Column

Column容器组件是沿垂直方向布局的容器。该组件从API Version 7开始支持,从API version 9开始,该接口支持在ArkTS卡片中使用。其可以包含子组件。

1.2.4.1 用法

Column组件用法如下:

Column(value?: {space?: string | number})
  • 1

以上参数解释如下:
在这里插入图片描述

Column组件支持很多通用属性,如:width、height等,还支持如下属性:
在这里插入图片描述

1.2.4.2 示例

以下代码定义了一个名为 ColumnExample 的组件,用于展示 Column 布局的不同特性,包括子元素间距、对齐方式和背景颜色。鸿蒙学习小助手V【hmos19】解答、咨询、项目实战

@Entry  // 使用 @Entry 装饰器标识这是一个入口组件。
@Component  // 使用 @Component 装饰器定义一个新组件。
struct ColumnExample {  // 定义名为 ColumnExample 的结构体,代表这个组件。

  build() {  // 定义 build 方法来构建UI。
    Column({ space: 5 }) {  // 创建一个 Column 组件,设置子元素间的垂直间距为5。
      Text('space').width('90%')  // 创建一个 Text 组件,说明接下来的内容与space属性相关。

      Column({ space: 5 }) {  // 创建一个内部 Column 组件,再次设置子元素间的垂直间距为5。
        Column().width('100%').height(30).backgroundColor(0xAFEEEE)  // 创建一个 Column 子组件,设置宽度、高度和背景颜色为浅蓝色。
        Column().width('100%').height(30).backgroundColor(0x00FFFF)  // 创建另一个 Column 子组件,设置宽度、高度和背景颜色为青色。
      }.width('90%').height(100).border({ width: 1 })  // 为这个内部 Column 设置宽度、高度和边框。

      // 设置子元素水平方向对齐方式
      Text('alignItems(Start)').width('90%')  // 创建一个 Text 组件,说明接下来的内容与水平起始对齐相关。
      Column() {  // 创建一个 Column 组件。
        Column().width('50%').height(30).backgroundColor(0xAFEEEE)  // 创建一个子 Column,设置宽度、高度和背景颜色为浅蓝色。
        Column().width('50%').height(30).backgroundColor(0x00FFFF)  // 创建另一个子 Column,设置宽度、高度和背景颜色为青色。
      }.alignItems(HorizontalAlign.Start).width('90%').border({ width: 1 })  // 为这个 Column 设置子元素水平起始对齐、宽度和边框。

      Text('alignItems(End)').width('90%')  // 创建一个 Text 组件,说明接下来的内容与水平结束对齐相关。
      Column() {  // 创建一个 Column 组件。
        Column().width('50%').height(30).backgroundColor(0xAFEEEE)  // 创建子 Column 组件,设置同上。
        Column().width('50%').height(30).backgroundColor(0x00FFFF)  // 创建另一个子 Column 组件,设置同上。
      }.alignItems(HorizontalAlign.End).width('90%').border({ width: 1 })  // 为这个 Column 设置子元素水平结束对齐、宽度和边框。

      Text('alignItems(Center)').width('90%')  // 创建一个 Text 组件,说明接下来的内容与水平居中对齐相关。
      Column() {  // 创建一个 Column 组件。
        Column().width('50%').height(30).backgroundColor(0xAFEEEE)  // 创建子 Column 组件,设置同上。
        Column().width('50%').height(30).backgroundColor(0x00FFFF)  // 创建另一个子 Column 组件,设置同上。
      }.alignItems(HorizontalAlign.Center).width('90%').border({ width: 1 })  // 为这个 Column 设置子元素水平居中对齐、宽度和边框。

      // 设置子元素垂直方向的对齐方式
      Text('justifyContent(Center)').width('90%')  // 创建一个 Text 组件,说明接下来的内容与垂直居中对齐相关。
      Column() {  // 创建一个 Column 组件。
        Column().width('90%').height(30).backgroundColor(0xAFEEEE)  // 创建子 Column 组件,设置宽度、高度和背景颜色为浅蓝色。
        Column().width('90%').height(30).backgroundColor(0x00FFFF)  // 创建另一个子 Column 组件,设置宽度、高度和背景颜色为青色。
      }.height(100).border({ width: 1 }).justifyContent(FlexAlign.Center)  // 为这个 Column 设置高度、边框和子元素垂直居中对齐。

      Text('justifyContent(End)').width('90%')  // 创建一个 Text 组件,说明接下来的内容与垂直结束对齐相关。
      Column() {  // 创建一个 Column 组件。
        Column().width('90%').height(30).backgroundColor(0xAFEEEE)  // 创建子 Column 组件,设置同上。
        Column().width('90%').height(30).backgroundColor(0x00FFFF)  // 创建另一个子 Column 组件,设置同上。
      }.height(100).border({ width: 1 }).justifyContent(FlexAlign.End)  // 为这个 Column 设置高度、边框和子元素垂直结束对齐。
    }.width('100%').padding({ top: 5 })  // 为最外层 Column 设置宽度和顶部内边距。
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

以上代码预览如下:

1.2.5 组件组件-Row
Row容器组件是沿水平方向布局容器。该组件从API Version 7开始支持,从API version 9开始,该接口支持在ArkTS卡片中使用。可以包含子组件。

1.2.5.1 用法

Row用法如下:

Row(value?:{space?: number | string })
  • 1

以上参数解释如下:

在这里插入图片描述

Row支持的属性如下:

在这里插入图片描述

更多示例可以加小助手获取…

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/421119
推荐阅读
相关标签
  

闽ICP备14008679号