ArkTS
- ■ JavaScript(JS)
- ■ TypeScript(TS)
- ■ ArkTS 简介
- ■ ArkTS 装饰器
- ■ @Builder装饰器:自定义构建函数
- ■ @Entry 页面的生命周期
- ■ @Component 自定义组件的生命周期
- ■ @State状态装饰器
- ■ @Track装饰器:class对象属性级更新
- ■ @Observed
- ■ @Prop装饰器-父子单向同步
- ■ @Link
- ■ @ObjectLink
- ■ @Watch
- ■ @Builder装饰器:自定义构建函数
- ■ @BuilderParam装饰器:引用@Builder函数
- ■ @LocalBuilder装饰器: 维持组件父子关系
- ■ @AnimatableExtend装饰器:定义可动画属性
- ■ @Require装饰器:校验构造传参
- ■ @Reusable装饰器:组件复用
- ■ @Watch装饰器:状态变量更改通知
- ■ @Styles装饰器:定义组件重用样式
- ■ @Extend装饰器:定义扩展组件样式
- ■ @Monitor装饰器:状态变量修改监听
- ■ @Param:组件外部输入
- ■ @Once:初始化同步一次
- ■ @Event装饰器:规范组件输出
- ■ @Provider装饰器和 @Consumer装饰器:跨组件层级双向同步
- ■ @Type装饰器:标记类属性的类型
- ■ 数据类型
- ■ 条件判断
- ■ 空安全 null
- ■ 非空断言运算符 !
- ■ 空值合并运算符 ??
- ■ 可选链
- ■ 循环
- ■ Throw和Try语句
- ■ 可迭代对象
- ■ 函数
- ■ 类 class
- ■ 接口 interface
- ■ 模块
- ■ 页面和自定义组件生命周期
- ■ 布局
- ■ 模块 (module)
- ■ Polygon 绘制组件
- ■ HSP (Harmony Shared Package)是动态共享包
- ■ HAR(Harmony Archive)是静态共享包,
- ■
■ JavaScript(JS)
■ TypeScript(TS)
TypeScript << JavaScript
TypeScript 是微软公式开发的一种基于 JavaScript(JS) 语言的编程语言。
TypeScript 是静态编译的编程语言,用于编写清晰简洁的JavaScript代码。
■ ArkTS 简介
ArkTS << TypeScript << JavaScript
■ ArkTS 装饰器
■ @Builder装饰器:自定义构建函数
■ 私有自定义构建函数
@Entry
@Component
struct BuilderDemo {
@Builder
showTextBuilder() {
Text('Hello World')
.fontSize(30)
.fontWeight(FontWeight.Bold)
}
@Builder
showTextValueBuilder(param: string) {
Text(param)
.fontSize(30)
.fontWeight(FontWeight.Bold)
}
build() {
Column() {
// 无参数
this.showTextBuilder()
// 有参数
this.showTextValueBuilder('Hello @Builder')
}
}
}
■ 全局自定义构建函数
@Builder
function showTextBuilder() {
Text('Hello World')
.fontSize(30)
.fontWeight(FontWeight.Bold)
}
@Entry
@Component
struct BuilderDemo {
build() {
Column() {
showTextBuilder()
}
}
}
■ 按值传递参数
状态变量的改变不会引起@Builder方法内的UI刷新
@Builder function overBuilder(paramA1: string) {
Row() {
Text(`UseStateVarByValue: ${paramA1} `)
}
}
@Entry
@Component
struct Parent {
@State ppppp: string = 'Hello';
build() {
Column() {
overBuilder(this.ppppp)
}
}
}
■ 按引用传递参数
按引用传递参数时,传递的参数可为状态变量,且状态变量的改变会引起@Builder方法内的UI刷新。
class Tmp {
paramA1: string = '';
}
@Builder function overBuilder(params: Tmp) {
Row() {
Text(`UseStateVarByReference: ${params.paramA1} `)
}
}
@Entry
@Component
struct Parent {
@State label: string = 'Hello';
build() {
Column() {
// 在父组件中调用overBuilder组件时,
// 把this.label通过引用传递的方式传给overBuilder组件。
overBuilder({ paramA1: this.label })
Button('Click me').onClick(() => {
// 单击Click me后,UI文本从Hello更改为ArkUI。
this.label = 'ArkUI';
})
}
}
}
■ @Entry 页面的生命周期
一个页面有且仅有一个@Entry入口。
■ @Component 自定义组件的生命周期
HarmonyOS的生命周期可以分为 @Compnent的生命周期和 @Entry的生命周期 也就是自定义组件的生命周期和页面的生命周期。
@Component和@Entry,ArkTS通过这两个关键字来装饰struct声明的数据结构,这个过程我们称为自定义组件。
组件内部需要提供一个build函数,我们在该函数体内按照链式调用的方式来描述整个页面的UI布局。
被Component装饰的struct称为UI组件。主要特征:
- 一个页面有且仅有一个@Entry入口。
- 一个页面可以包含一个或多个component;
- 每个component都必须实现 build 方法来更新UI;
- 一个component内部还可以调用另外一个component;
示例
@Entry //一个页面有且仅有一个@Entry入口。
@Component //一个页面可以包含一个或多个component;
struct MainComponent {
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Text('Black is MainComponent')
.fontSize(26)
.fontColor(Color.Black)
.height(50)
SubComponent() //调用
}
.width('100%')
.height('100%')
}
}
@Component //一个页面可以包含一个或多个component;
struct SubComponent {
build() {
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Text('Red is SubComponent')
.fontSize(26)
.fontWeight(500)
.fontColor(Color.Red)
}
.width('100%')
}
}
■ @State状态装饰器
@State装饰的变量,或称为状态变量,一旦变量拥有了状态属性,就和自定义组件的渲染绑定起来。
当状态改变时,UI会发生对应的渲染改变。
■ @Track装饰器:class对象属性级更新
■ @Observed
■ @Prop装饰器-父子单向同步
■ @Link
■ @ObjectLink
■ @Watch
@Watch用于监听状态变量的变化,当状态变量变化时,@Watch的回调方法将被调用.
■ @Builder装饰器:自定义构建函数
■ @BuilderParam装饰器:引用@Builder函数
■ @LocalBuilder装饰器: 维持组件父子关系
■ @AnimatableExtend装饰器:定义可动画属性
■ @Require装饰器:校验构造传参
■ @Reusable装饰器:组件复用
■ @Watch装饰器:状态变量更改通知
■ @Styles装饰器:定义组件重用样式
■ @Extend装饰器:定义扩展组件样式
■ @Monitor装饰器:状态变量修改监听
■ @Param:组件外部输入
■ @Once:初始化同步一次
■ @Event装饰器:规范组件输出
■ @Provider装饰器和 @Consumer装饰器:跨组件层级双向同步
■ @Type装饰器:标记类属性的类型
■ 数据类型
■ let
以关键字let开头的声明引入变量,该变量在程序执行期间可以具有不同的值
let hi: string = 'hello';
hi = 'hello, world';
常量声明
const hello: string = 'hello'; //以关键字const开头的声明引入只读常量,该常量只能被赋值一次。
自动类型推断
自动类型推断
let hi1: string = 'hello'; //显式指定其类型
let hi2 = 'hello, world'; //自动推断类型
■ boolean
■ 数字 number
ArkTS提供number类型,任何整数和浮点数都可以被赋给此类型的变量。
整数字面量
十进制整数 例如:0、117、-345
十六进制整数 0x1123、0x00111、-0xF1A7
八进制整数 以0o(或0O)开头的八进制整数,只能包含数字(0-7)。例如:0o777
二进制整数 以0b(或0B)开头的二进制整数,只能包含数字0和1。例如:0b11、0b0011、-0b11
浮点字面量
十进制整数,可为有符号数(即,前缀为“+”或“-”);
小数点(“.”)
小数部分(由十进制数字字符串表示)
以“e”或“E”开头的指数部分,后跟有符号(即,前缀为“+”或“-”)或无符号整数。
let n1 = 3.14;
let n2 = 3.141592;
let n3 = .5;
let n4 = 1e2;
function factorial(n: number): number {
if (n <= 1) {
return 1;
}
return n * factorial(n - 1);
}
factorial(n1) // 7.660344000000002
factorial(n2) // 7.680640444893748
factorial(n3) // 1
factorial(n4) // 9.33262154439441e+157
umber类型在表示大整数时会造成精度丢失。在开发时可以按需使用bigInt类型来确保精度:
let bigIntger: BigInt = BigInt('999999999999999999999999999999999999999999999999999999999999');
console.log('bigIntger' + bigIntger.toString());
■ 字符串 string
let s1 = 'Hello, world!\n'; //单引号(')
let s2 = "this is a string"; //双引号(")
let a = 'Success';
let s3 = `The result is ${a}`; //是用反向单引号(`)括起来的模板字面量。
■ 数组
■ 元组
■ 枚举
■ Unknown
■ void
■ null, undefind
■ Object类型
object类型则用于表示除基本类型外的类型。
■ array类型
let names: string[] = ['Alice', 'Bob', 'Carol'];
■ Union 联合
union类型,即联合类型,是由多个类型组合成的引用类型。
联合类型包含了变量可能的所有类型。
class Cat {
name: string = 'cat';
// ...
}
class Dog {
name: string = 'dog';
// ...
}
class Frog {
name: string = 'frog';
// ...
}
type Animal = Cat | Dog | Frog | number;
// Cat、Dog、Frog是一些类型(类或接口)
let animal: Animal = new Cat();
animal = new Frog();
animal = 42;
// 可以将类型为联合类型的变量赋值为任何组成类型的有效值
可以用不同的机制获取联合类型中特定类型的值。
class Cat { sleep () {}; meow () {} }
class Dog { sleep () {}; bark () {} }
class Frog { sleep () {}; leap () {} }
type Animal = Cat | Dog | Frog;
function foo(animal: Animal) {
if (animal instanceof Frog) {
animal.leap(); // animal在这里是Frog类型
}
animal.sleep(); // Animal具有sleep方法
}
■ enum 类型
使用枚举常量时必须以枚举类型名称为前缀。
enum ColorSet { Red, Green, Blue }
let c: ColorSet = ColorSet.Red;
常量表达式可以用于显式设置枚举常量的值。
enum ColorSet { White = 0xFF, Grey = 0x7F, Black = 0x00 }
let c: ColorSet = ColorSet.Black;
■ Aliases 别名类型
Aliases类型为匿名类型(数组、函数、对象字面量或联合类型)提供名称,或为已有类型提供替代名称。
type Matrix = number[][];
type Handler = (s: string, no: number) => string;
type Predicate <T> = (x: T) => boolean;
type NullableObject = Object | null;
■ 返回类型
// 显式指定返回类型
function foo(): string { return 'foo'; }
// 推断返回类型为string
function goo() { return 'goo'; }
//不需要返回值
function hi1() { console.log('hi'); }
function hi2(): void { console.log('hi'); }
■ 条件判断
■ if else
■ switch
■ 空安全 null
let x: number = null; // 编译时错误
let y: string = null; // 编译时错误
let z: number[] = null; // 编译时错误
let x: number | null = null; //为空值的变量定义为联合类型T | null。
x = 1; // ok
x = null; // ok
if (x != null) { /* do something */ }
■ 非空断言运算符 !
后缀运算符!可用于断言其操作数为非空。
class A {
value: number = 0;
}
function foo(a: A | null) {
a.value; // 编译时错误:无法访问可空值的属性
a!.value; // 编译通过,如果运行时a的值非空,可以访问到a的属性;如果运行时a的值为空,则发生运行时异常
}
■ 空值合并运算符 ??
a ?? b等价于三元运算符(a != null && a != undefined) ? a : b。
class Person {
// ...
nick: string | null = null;
getNick(): string {
return this.nick ?? ''; //
}
}
■ 可选链
在访问对象属性时,如果该属性是undefined或者null,可选链运算符会返回undefined。
class Person {
nick: string | null = null;
spouse?: Person
setSpouse(spouse: Person): void {
this.spouse = spouse;
}
getSpouseNick(): string | null | undefined {
return this.spouse?.nick;
}
constructor(nick: string) {
this.nick = nick;
this.spouse = undefined;
}
}
■ 循环
■ for()
■ Throw和Try语句
try {
// 可能发生异常的语句块
} catch (e) {
// 异常处理
}
■ 可迭代对象
■ for… of
■ for… in
■ Map类型
K 打印
K[1] 打印
■ 函数
■ 普通函数
■ 普通函数:带返回值
■ 箭头函数 (又名Lambda函数) 匿名函数 v斜体样式
//回类型可以省略 返回类型通过函数体推断
//以下两种表达方式是等价的
let sum1 = (x: number, y: number) => { return x + y; } //
let sum2 = (x: number, y: number) => x + y
■ 可选参数的函数
■ 函数-可选参数
可选参数的格式可为name?: Type。
在这里插入代码片
■ 函数-参数默认值
function multiply(n: number, coeff: number = 2): number {
return n * coeff;
}
multiply(2); // 返回2*2
multiply(2, 3); // 返回2*3
■ 函数-Rest 剩余参数
函数的最后一个参数可以是rest参数。rest参数的格式为…restArgs。
rest参数允许函数接收一个由剩余实参组成的数组,用于处理不定数量的参数输入。
function sum(...numbers: number[]): number {
let res = 0;
for (let n of numbers)
res += n;
return res;
}
sum(); // 返回0
sum(1, 2, 3); // 返回6
■ 函数-函数重载
function foo(x: number): void; /* 第一个函数定义 */
function foo(x: string): void; /* 第二个函数定义 */
function foo(x: number | string): void { /* 函数实现 */
}
foo(123); // OK,使用第一个定义
foo('aa'); // OK,使用第二个定义
■ 函数-泛型函数
function last(x: number[]): number {
return x[x.length - 1];
}
last([1, 2, 3]); // 3
如果需要为任何数组定义相同的函数,使用类型参数将该函数定义为泛型:
function last<T>(x: T[]): T {
return x[x.length - 1];
}
// 显式设置的类型实参
last<string>(['aa', 'bb']);
last<number>([1, 2, 3]);
// 隐式设置的类型实参
// 编译器根据调用参数的类型来确定类型实参
last([1, 2, 3]);
■ 类 class
■ 定义类
■ 继承 extends
■ 字段
字段是直接在类中声明的某种类型的变量。
==静态字段: ==
使用关键字static将字段声明为静态。静态字段属于类本身,类的所有实例共享一个静态字段。
class Person {
static numberOfPersons = 0;
constructor() {
// ...
Person.numberOfPersons++;
// ...
}
}
Person.numberOfPersons;
== ==
■ getter和setter
setter和getter可用于提供对对象属性的受控访问。
class Person {
name: string = '';
private _age: number = 0;
get age(): number { return this._age; }
set age(x: number) { //setter用于禁止将_age属性设置为无效值:
if (x < 0) {
throw Error('Invalid age argument');
}
this._age = x;
}
}
let p = new Person();
p.age; // 输出0
p.age = -42; // 设置无效age值会抛出错误
■ 接口 interface
任何一个类的实例只要实现了特定接口,就可以通过该接口实现多态。
// 接口:
interface AreaSize {
calculateAreaSize(): number; // 方法的声明
someMethod(): void; // 方法的声明
}
// 实现:
class RectangleSize implements AreaSize {
private width: number = 0;
private height: number = 0;
someMethod(): void {
console.log('someMethod called');
}
calculateAreaSize(): number {
this.someMethod(); // 调用另一个方法并返回结果
return this.width * this.height;
}
}
■ 接口继承
interface Style {
color: string;
}
interface ExtendedStyle extends Style {
width: number;
}
■ 模块
■ 导出 export
■ 静态导入 import
■ 动态导入 import()
// Calc.ts
export function add(a:number, b:number):number {
let c = a + b;
console.info('Dynamic import, %d + %d = %d', a, b, c);
return c;
}
// Index.ts
import("./Calc").then((obj: ESObject) => {
console.info(obj.add(3, 5));
}).catch((err: Error) => {
console.error("Module dynamic import error: ", err);
});
■ 页面和自定义组件生命周期
onPageShow:页面每次显示时触发一次,包括路由过程、应用进入前台等场景。
onPageHide:页面每次隐藏时触发一次,包括路由过程、应用进入后台等场景。
onBackPress:当用户点击返回按钮时触发。
aboutToAppear:组件即将出现时回调该接口,具体时机为在创建自定义组件的新实例后,在执行其build()函数之前执行。
onDidBuild:组件build()函数执行完成之后回调该接口,开发者可以在这个阶段进行埋点数据上报等不影响实际UI的功能。不建议在onDidBuild函数中更改状态变量、使用animateTo等功能,这可能会导致不稳定的UI表现。
aboutToDisappear:aboutToDisappear函数在自定义组件析构销毁之前执行。不允许在aboutToDisappear函数中改变状态变量,特别是@Link变量的修改可能会导致应用程序行为不稳定。
■
■ 布局
■
■
■
■ RelativeContainer 相对布局
锚点:通过锚点设置当前元素基于哪个元素确定位置。
对齐方式:通过对齐方式,设置当前元素是基于锚点的上中下对齐,还是基于锚点的左中右对齐。
在水平方向上,可以设置left、middle、right的锚点。
在竖直方向上,可以设置top、center、bottom的锚点
@Entry
@Component
struct RelativeContainerTest {
build() {
RelativeContainer(){
Column() {
Text('1111111111').textAlign(TextAlign.End).fontSize(20)
}
.width(100)
.height(100)
.backgroundColor(0xffd306)
.id("column1")
.alignRules({
top:{'anchor':'__container__',align:VerticalAlign.Top},
left:{'anchor': '__container__', align: HorizontalAlign.Start}
})
Column() {
Text('22222222').fontSize(20)
}
.width(100)
.height(100)
.backgroundColor(Color.Pink)
.id("column2")
.alignRules({
top:{'anchor':'column1',align:VerticalAlign.Top},
left:{'anchor': 'column1', align: HorizontalAlign.End}
})
}
.backgroundColor(Color.Grey)
.width(300)
.height(300)
}
}
■ 模块 (module)
■ import 导入
- import {Employee} from ‘./person’
■ export 导出
- export class Person //导出 Person 类
- export class Employee extends Person //导出 Employee 类