赞
踩
ArkTS 是 HarmonyOS 优选的主力应用开发语言。它在TypeScript(简称TS)的基础上,匹配 ArkUI 框架,扩展了声明式 UI、状态管理等相应的能力,让开发者以更简洁、更自然的方式开发跨端应用。
要了解什么是 ArkTS,我们首先要了解下 ArkTS、TypeScript 和 JavaScript 之间的关系:
JavaScript 是一种属于网络的高级脚本语言,已经被广泛用于 Web 应用开发,常用来为网页添加各式各样的动态功能,为用户提供更流畅美观的浏览效果。
TypeScript 是 JavaScript 的一个超集,它扩展了 JavaScript 的语法,通过在 JavaScript 的基础上添加静态类型定义构建而成,是一个开源的编程语言。
ArkTS 兼容 TypeScript 语言,拓展了声明式 UI、状态管理、并发任务等能力。
由此可知,TypeScript 是 JavaScript 的超集,ArkTS 则是 TypeScript 的超集,他们的关系如下图所示:
在学习 ArkTS 声明式的相关语法之前,我们首先需要掌握 TypeScript的基础语法。
TypeScript 中可以使用 boolean
来表示这个变量是布尔值,可以赋值为 true 或者 false。
let isDone: boolean = false;
TypeScript 里的所有数字都是浮点数,这些浮点数的类型是 number
。除了支持十进制,还支持二进制、八进制、十六进制。
let decLiteral: number = 6;
let hexLiteral: number = 0xf00d;
let binaryLiteral: number = 0b1010;
let octalLiteral: number = 0o744;
TypeScript 里使用 string
表示文本数据类型, 可以使用双引号(")或单引号(')表示字符串。
let name: string = "bob";
name = "smith";
name = 'Mick';
TypeScript 像 JavaScript 一样可以操作数组元素, 有两种方式可以定义数组。
第一种,可以在元素类型后面接上 []
,表示由此类型元素组成的一个数组:
let list: number[] = [1, 2, 3];
第二种方式是使用数组泛型,Array<元素类型>:
let list: Array<number> = [1, 2, 3];
元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同。 比如,你可以定义一对值分别为 string
和 number
类型的元组。
let x: [string, number];
x = ['hello', 10]; // OK
x = [10, 'hello']; // Error
enum
类型是对 JavaScript 标准数据类型的一个补充。 像 C# 等其它语言一样,使用枚举类型可以为一组数值赋予友好的名字。
enum Color {Red, Green, Blue}
let c: Color = Color.Green;
有时候,我们会想要为那些在编程阶段还不清楚类型的变量指定一个类型。 这些值可能来自于动态的内容,比如来自用户输入或第三方代码库。 这种情况下,我们不希望类型检查器对这些值进行检查而是直接让它们通过编译阶段的检查。 那么我们可以使用 any
类型来标记这些变量:
let notSure: any = 4;
notSure = "maybe a string instead";
notSure = false; // okay, definitely a boolean
某种程度上来说,void
类型像是与 any
类型相反,它表示没有任何类型。 当一个函数没有返回值时,你通常会见到其返回值类型是 void
:
function warnUser(): void {
alert("This is my warning message");
}
TypeScrip t里,undefined
和 null
两者各自有自己的类型分别叫做 undefined
和 null
。 和void
相似,它们的本身的类型用处不是很大:
let u: undefined = undefined;
let n: null = null;
联合类型(Union Types)表示取值可以为多种类型中的一种。
let myFavoriteNumber: string | number;
myFavoriteNumber = 'seven';
myFavoriteNumber = 7;
有时候你会遇到这样的情况,你会比TypeScript更了解某个值的详细信息。 通常这会发生在你清楚地知道一个实体具有比它现有类型更确切的类型。
通过类型断言这种方式可以告诉编译器,“相信我,我知道自己在干什么”。 类型断言好比其它语言里的类型转换,但是不进行特殊的数据检查和解构。 它没有运行时的影响,只是在编译阶段起作用。 TypeScript 会假设你已经进行了必须的检查。
类型断言有两种形式。 其一是“尖括号”语法:
let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;
另一个为 as
语法:
let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;
两种形式是等价的,至于使用哪个大多数情况下是凭个人喜好。
你可能已经注意到了,前面的代码示例都是使用 let
关键字来代替我们所熟悉的 JavaScript 关键字 var
。 let
关键字是 JavaScript 的一个新概念,TypeScript 实现了它。 很多常见的问题都可以通过使用 let
来解决,所以尽可能地使用 let
来代替 var
。
TypeScript if 语句由一个布尔表达式后跟一个或多个语句组成。
var num:number = 5
if (num > 0) {
console.log('数字是正数')
}
一个 if 语句后可跟一个可选的 else 语句,else 语句在布尔表达式为 false 时执行。
var num:number = 12;
if (num % 2==0) {
console.log('偶数');
} else {
console.log('奇数');
}
if…else if…else 语句在执行多个判断条件的时候很有用。
var num:number = 2
if(num > 0) {
console.log(num+' 是正数')
} else if(num < 0) {
console.log(num+' 是负数')
} else {
console.log(num+' 为0')
}
一个 switch 语句允许测试一个变量等于多个值时的情况。每个值称为一个 case,且被测试的变量会对每个 switch case 进行检查。
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; } }
函数是一组一起执行一个任务的语句,函数声明要告诉编译器函数的名称、返回类型和参数。TypeScript 可以创建有名字的函数和匿名函数,其创建方法如下:
// 有名函数
function add(x, y) {
return x + y;
}
// 匿名函数
let myAdd = function (x, y) {
return x + y;
};
为了确保输入输出的准确性,我们可以为上面那个函数添加类型:
// 有名函数:给变量设置为 number 类型
function add(x: number, y: number): number {
return x + y;
}
// 匿名函数:给变量设置为 number 类型
let myAdd = function (x: number, y: number): number {
return x + y;
};
在 TypeScript 里我们可以在参数名旁使用 ?
实现可选参数的功能。 比如,我们想让 lastName 是可选的:
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)
接下来我们看看如何将我们熟悉的函数定义方式转换为箭头函数,我们可以定义一个判断正负数的函数,如下:
function testNumber(num: number) {
if (num > 0) {
console.log(num + ' 是正数');
} else if (num < 0) {
console.log(num + ' 是负数');
} else {
console.log(num + ' 为0');
}
}
其调用方法如下:
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');
}
}
其调用方法如下:
testArrowFun(-1) //输出日志:-1 是负数
后面,我们在学习 HarmonyOS 应用开发时会经常用到箭头函数。
例如,给一个按钮添加点击事件,其中 onClick 事件中的函数就是箭头函数。
Button("Click Now")
.onClick(() => {
console.info("Button is click")
})
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}`;
}
}
通过上面的 Person 类,我们可以定义一个人物 Jacky 并获取他的基本信息,其定义如下:
let person1 = new Person('Jacky', 18);
person1.getPersonInfo();
继承就是子类继承父类的特征和行为,使得子类具有父类相同的行为。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}`;
}
}
通过上面的 Employee 类,我们可以定义一个人物 Tom,这里可以获取他的基本信息,也可以获取他的雇主信息,其定义如下:
let person2 = new Employee('Tom', 28, 'HuaWei');
person2.getPersonInfo();
person2.getEmployeeInfo();
在 TypeScript 中,有 public、private、protected 修饰符,其功能和具体使用场景可以参考 TypeScript 的相关学习资料,进行拓展学习。
随着应用越来越大,通常要将代码拆分成多个文件,即所谓的模块(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;
}
}
模块的导入操作与导出一样简单。 可以使用以下 import
形式之一来导入其它模块中的导出内容。
import { NewsData } from '../common/bean/NewsData';
当一个对象实现了 Symbol.iterator 属性时,我们认为它是可迭代的。一些内置的类型如 Array,Map,Set,String,Int32Array,Uint32Array 等都具有可迭代性。
for..of
会遍历可迭代的对象,调用对象上的 Symbol.iterator 方法。 下面是在数组上使用 for…of 的简单例子:
let someArray = [1, "string", false];
for (let entry of someArray) {
console.log(entry); // 1, "string", false
}
for..of
和 for..in
均可迭代一个列表,但是用于迭代的值却不同:
for…in 迭代的是 对象的键,而 for…of 则迭代的是对象的值。
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"
}
TypeScript 是一个开源的编程语言,本文只介绍了 TypeScript 的基础语法知识,更多内容可以参考 TypeScript 的官方教程。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。