ArkTS 语言基础
ArkTS 是华为基于 TypeScript 扩展而来的声明式编程语言,专为 HarmonyOS 应用开发设计。它在保持 TypeScript 语法特性的基础上,增加了声明式 UI、状态管理和严格的类型约束,以确保更好的运行时性能和类型安全。
与 TypeScript 的区别
ArkTS 在 TypeScript 基础上增加了一些限制,以确保更好的性能和类型安全:
| 特性 | TypeScript | ArkTS |
|---|---|---|
any 类型 | 允许 | 禁止 |
| 动态属性添加 | 允许 | 禁止 |
eval / new Function | 允许 | 禁止 |
| 声明式 UI | 不支持 | 支持 |
| 状态管理装饰器 | 不支持 | 支持 |
| 并发模型 | 单线程 | TaskPool/Worker |
// ❌ 错误(ArkTS 不允许)
let a: any = 1
a = 'x'
const obj = {}
obj.name = '张三'
// ✅ 正确
let a: number = 1
class Person {
name: string = ''
}
const obj: Person = { name: '张三' }提示
ArkTS 的严格类型检查在编译阶段就能发现大部分错误,建议始终显式声明类型。
基本数据类型
ArkTS 支持 TypeScript 的所有基本数据类型:
number
数字类型,包括整数和浮点数:
let integer: number = 42
let floating: number = 3.14
let hex: number = 0xff // 十六进制
let binary: number = 0b1010 // 二进制
let octal: number = 0o744 // 八进制
let infinity: number = Infinity
let notANumber: number = NaNstring
字符串类型,支持单引号、双引号和模板字符串:
let single: string = 'Hello'
let double: string = "World"
let name: string = 'ArkTS'
let greeting: string = `Welcome to ${name}!`
let multiLine: string = `
第一行
第二行
第三行
`boolean
布尔类型:
let isDone: boolean = false
let isValid: boolean = truenull 和 undefined
let n: null = null
let u: undefined = undefined
// 联合类型使用
let value: string | null = null
value = 'hello'symbol
Symbol 类型用于创建唯一的标识符:
let sym1: symbol = Symbol('key')
let sym2: symbol = Symbol('key')
console.info(sym1 === sym2) // false,每个 Symbol 都是唯一的
// 用作对象属性键
const id: symbol = Symbol('id')bigint
BigInt 类型用于表示任意大的整数:
let big: bigint = 9007199254740991n
let another: bigint = BigInt(123)
// 大数运算
let sum: bigint = big + 1nvoid
void 表示没有返回值,通常用于函数:
function logMessage(msg: string): void {
console.info(msg)
}联合类型
联合类型表示一个值可以是多种类型之一:
type Status = 'idle' | 'loading' | 'done'
let currentStatus: Status = 'idle'
// 数字或字符串
type ID = number | string
let userId: ID = 1001
userId = 'U1001'数组和元组
Array 数组
数组用于存储有序数据集合,提供两种声明方式:
// 方式一:类型后缀
let numbers: number[] = [1, 2, 3]
let strings: string[] = ['a', 'b', 'c']
// 方式二:泛型语法
let arr1: Array<number> = [1, 2, 3]
let arr2: Array<string> = ['a', 'b']
// 多维数组
let matrix: number[][] = [[1, 2], [3, 4]]
// 数组方法
let nums: number[] = [1, 2, 3]
nums.push(4) // 添加元素
nums.pop() // 移除最后一个
nums.shift() // 移除第一个
nums.unshift(0) // 在开头添加
nums.splice(1, 1) // 删除指定位置
let sliced: number[] = nums.slice(0, 2) // 截取ArrayList
ArkTS 提供了 @arkts.collections 中的 ArrayList:
import { collections } from '@kit.ArkTS'
let list: collections.ArrayList<number> = new collections.ArrayList()
list.add(1)
list.add(2)
list.add(3)
console.info(list.get(0)) // 1
console.info(list.size()) // 3Set 集合
Set 存储唯一值:
let uniqueNums: Set<number> = new Set([1, 2, 2, 3])
console.info(uniqueNums.size) // 2
uniqueNums.add(4)
uniqueNums.delete(1)
uniqueNums.has(2) // true
uniqueNums.clear()Map 映射
Map 存储键值对:
let userMap: Map<string, number> = new Map()
userMap.set('Alice', 25)
userMap.set('Bob', 30)
console.info(userMap.get('Alice')) // 25
console.info(userMap.has('Bob')) // true
userMap.delete('Alice')
console.info(userMap.size) // 1
// 遍历
for (let [key, value] of userMap) {
console.info(`${key}: ${value}`)
}元组 Tuple
元组表示固定长度、固定类型的数组:
// 定义元组类型
let person: [string, number] = ['张三', 25]
// 可选元素
let optionalTuple: [string, number?] = ['hello']
optionalTuple = ['hello', 42]
// 剩余元素
let restTuple: [string, ...number[]] = ['scores', 90, 85, 88]
// 只读元组
let readonlyTuple: readonly [string, number] = ['a', 1]
// readonlyTuple[0] = 'b' // ❌ 错误:无法修改接口与类
接口 Interface
接口定义对象的结构契约:
// 基础接口
interface User {
id: number
name: string
age?: number // 可选属性
readonly email: string // 只读属性
}
const user: User = {
id: 1,
name: '张三',
email: 'zhangsan@example.com'
}
// 接口继承
interface Animal {
name: string
}
interface Dog extends Animal {
breed: string
}
const myDog: Dog = {
name: '旺财',
breed: '金毛'
}
// 接口定义函数类型
interface SearchFunc {
(source: string, subString: string): boolean
}
let mySearch: SearchFunc = function(src: string, sub: string): boolean {
return src.indexOf(sub) > -1
}
// 接口定义索引签名
interface StringArray {
[index: number]: string
}
let myArray: StringArray = ['Bob', 'Fred']类 Class
// 基础类
class Account {
balance: number = 0
deposit(amount: number): void {
this.balance += amount
}
withdraw(amount: number): boolean {
if (this.balance >= amount) {
this.balance -= amount
return true
}
return false
}
}
const account = new Account()
account.deposit(100)
console.info('余额:', account.balance)访问修饰符
class Person {
public name: string = '' // 公开(默认)
private age: number = 0 // 私有
protected id: string = '' // 受保护
readonly email: string = '' // 只读
constructor(name: string, age: number) {
this.name = name
this.age = age
}
public getAge(): number {
return this.age
}
private setAge(age: number): void {
this.age = age
}
}
class Employee extends Person {
constructor(name: string, age: number, id: string) {
super(name, age)
this.id = id // 可以访问 protected
// this.age = age // ❌ 错误:无法访问 private
}
}抽象类
abstract class Animal {
abstract makeSound(): void // 抽象方法
move(): void {
console.info('移动中...')
}
}
class Dog extends Animal {
makeSound(): void {
console.info('汪汪!')
}
}
// let animal = new Animal() // ❌ 错误:不能实例化抽象类
let dog = new Dog()
dog.makeSound()
dog.move()接口实现
interface CanFly {
fly(): void
}
interface CanSwim {
swim(): void
}
// 实现多个接口
class Duck implements CanFly, CanSwim {
fly(): void {
console.info('鸭子在飞')
}
swim(): void {
console.info('鸭子在游泳')
}
}函数
函数声明
// 命名函数
function add(a: number, b: number): number {
return a + b
}
// 函数表达式
let multiply = function(a: number, b: number): number {
return a * b
}箭头函数
// 基本箭头函数
let square = (x: number): number => x * x
// 多行箭头函数
let greet = (name: string): string => {
let prefix: string = 'Hello, '
return prefix + name
}
// 无参数
let getRandom = (): number => Math.random()
// 多个参数
let concat = (a: string, b: string): string => a + b默认参数
function greetUser(name: string, greeting: string = 'Hello'): string {
return `${greeting}, ${name}!`
}
console.info(greetUser('张三')) // Hello, 张三!
console.info(greetUser('李四', 'Hi')) // Hi, 李四!剩余参数
function sum(...numbers: number[]): number {
return numbers.reduce((total, num) => total + num, 0)
}
console.info(sum(1, 2, 3, 4)) // 10
// 与其他参数结合
function greetEveryone(greeting: string, ...names: string[]): string {
return `${greeting}, ${names.join(' 和 ')}!`
}函数重载
// 重载签名
function process(input: string): string
function process(input: number): number
function process(input: boolean): boolean
// 实现签名
function process(input: string | number | boolean): string | number | boolean {
if (typeof input === 'string') {
return input.toUpperCase()
} else if (typeof input === 'number') {
return input * 2
} else {
return !input
}
}
console.info(process('hello')) // HELLO
console.info(process(42)) // 84
console.info(process(true)) // false函数类型
// 定义函数类型
type MathOperation = (a: number, b: number) => number
let add: MathOperation = (x, y) => x + y
let subtract: MathOperation = (x, y) => x - y
// 回调函数类型
function processArray(arr: number[], callback: (item: number) => void): void {
for (let item of arr) {
callback(item)
}
}
processArray([1, 2, 3], (item) => {
console.info(item)
})泛型
泛型让函数、接口和类可以与多种类型一起工作,提供类型安全的同时保持灵活性。
泛型函数
function first<T>(arr: T[]): T | undefined {
return arr[0]
}
const firstNum = first<number>([1, 2, 3]) // number | undefined
const firstStr = first<string>(['a', 'b']) // string | undefined
// 泛型约束
interface HasLength {
length: number
}
function logLength<T extends HasLength>(arg: T): T {
console.info(arg.length)
return arg
}
logLength('hello') // 5
logLength([1, 2, 3]) // 3
// logLength(123) // ❌ 错误:number 没有 length 属性泛型接口
interface Response<T> {
code: number
data: T
message: string
}
interface UserData {
id: number
name: string
}
const userResponse: Response<UserData> = {
code: 200,
data: { id: 1, name: '张三' },
message: 'success'
}
// 泛型接口与函数
interface GenericIdentityFn<T> {
(arg: T): T
}
let identity: GenericIdentityFn<number> = (x) => x泛型类
class GenericNumber<T> {
zeroValue: T
add: (x: T, y: T) => T
constructor(zeroValue: T, addFn: (x: T, y: T) => T) {
this.zeroValue = zeroValue
this.add = addFn
}
}
let myGenericNumber = new GenericNumber<number>(0, (x, y) => x + y)
console.info(myGenericNumber.add(5, 3)) // 8
// 泛型约束示例
class Repository<T extends { id: number }> {
private items: T[] = []
add(item: T): void {
this.items.push(item)
}
findById(id: number): T | undefined {
return this.items.find(item => item.id === id)
}
}
interface Product {
id: number
name: string
price: number
}
let productRepo = new Repository<Product>()
productRepo.add({ id: 1, name: '手机', price: 2999 })条件类型
type IsString<T> = T extends string ? true : false
type A = IsString<string> // true
type B = IsString<number> // false
// 实用工具类型
type NonNullable<T> = T extends null | undefined ? never : T
type MaybeString = string | null
type DefinitelyString = NonNullable<MaybeString> // string枚举
数字枚举
enum Direction {
Up, // 0
Down, // 1
Left, // 2
Right // 3
}
let dir: Direction = Direction.Up
console.info(dir) // 0
// 指定起始值
enum Color {
Red = 1,
Green, // 2
Blue // 3
}
// 完全指定值
enum HttpStatus {
OK = 200,
NotFound = 404,
ServerError = 500
}
console.info(HttpStatus.OK) // 200
console.info(HttpStatus['OK']) // 200
console.info(HttpStatus[200]) // OK字符串枚举
enum DirectionStr {
Up = 'UP',
Down = 'DOWN',
Left = 'LEFT',
Right = 'RIGHT'
}
console.info(DirectionStr.Up) // UP异构枚举
enum Mixed {
No = 0,
Yes = 'YES',
Maybe = 2
}常量枚举
const enum DirectionConst {
Up,
Down,
Left,
Right
}
// 编译时内联,不会生成对象
let directions = [DirectionConst.Up, DirectionConst.Down]类型别名、联合类型与交叉类型
类型别名
// 基本类型别名
type UserID = number
type UserName = string
// 对象类型别名
type Point = {
x: number
y: number
}
let p: Point = { x: 10, y: 20 }
// 联合类型别名
type Status = 'pending' | 'success' | 'error'
type ID = string | number
// 函数类型别名
type Callback = (data: string) => void
// 与接口的区别:类型别名可以为任意类型起名字
type StringOrNumber = string | number
type TupleType = [string, number]联合类型
function printId(id: number | string): void {
if (typeof id === 'string') {
console.info(id.toUpperCase())
} else {
console.info(id.toFixed(2))
}
}
printId(101) // 101.00
printId('abc') // ABC
// 字面量联合类型
type EventType = 'click' | 'dblclick' | 'mouseup' | 'mousedown'
function handleEvent(event: EventType): void {
console.info(`处理 ${event} 事件`)
}交叉类型
interface Colorful {
color: string
}
interface Circle {
radius: number
}
type ColorfulCircle = Colorful & Circle
let cc: ColorfulCircle = {
color: 'red',
radius: 42
}
// 多个接口交叉
interface Employee {
name: string
}
interface Manager {
department: string
}
type ManagerEmployee = Employee & Manager
let manager: ManagerEmployee = {
name: '张三',
department: '技术部'
}类型推断与类型断言
类型推断
// 变量类型推断
let x = 3 // 推断为 number
let y = 'hello' // 推断为 string
let z = [1, 2] // 推断为 number[]
// 函数返回值推断
function add(a: number, b: number) {
return a + b // 推断返回 number
}
// 上下文类型推断
window.onscroll = function(event) {
// event 被推断为 Event 类型
console.info(event.target)
}类型断言
// as 语法
let someValue: unknown = 'this is a string'
let strLength: number = (someValue as string).length
// 尖括号语法(在 TSX 中不可用)
let anotherLength: number = (<string>someValue).length
// 非空断言
function process(value: string | null) {
const len = value!.length // 确定 value 不为 null
}
// 双重断言
let value: unknown = 'hello'
let num = (value as unknown as number) // 谨慎使用注意
类型断言不会进行运行时检查,仅在编译时起作用。如果断言错误,可能导致运行时异常。
装饰器
ArkTS 使用装饰器实现声明式 UI 和状态管理。以下是所有核心装饰器的详细说明。
组件装饰器
@Entry
标记入口组件,每个页面必须有且只有一个:
@Entry
@Component
struct Index {
build() {
Column() {
Text('首页')
}
}
}@Component
标记自定义组件:
@Component
struct MyComponent {
build() {
Row() {
Text('自定义组件')
}
}
}状态管理装饰器
@State
组件内部状态,变化触发 UI 刷新:
@Entry
@Component
struct CounterPage {
@State count: number = 0
build() {
Column() {
Text(`点击次数: ${this.count}`)
.fontSize(30)
Button('增加')
.onClick(() => {
this.count++
})
}
}
}规则说明:
| 特性 | 说明 |
|---|---|
| 同步类型 | 不与父组件同步 |
| 允许类型 | Object、class、string、number、boolean、enum、Array、Date、Map、Set |
| 初始值 | 必须本地初始化 |
| 外部访问 | 不支持,仅组件内访问 |
@Prop
父子单向同步,父变子变,子变父不变:
@Component
struct Child {
@Prop count: number = 0
build() {
Column() {
Text(`子组件: ${this.count}`)
Button('子组件修改')
.onClick(() => {
this.count++ // 仅本地生效,不会同步回父组件
})
}
}
}
@Entry
@Component
struct Parent {
@State parentCount: number = 10
build() {
Column() {
Text(`父组件: ${this.parentCount}`)
Button('父组件修改')
.onClick(() => {
this.parentCount++
})
Child({ count: this.parentCount })
}
}
}@Link
父子双向同步:
@Component
struct LinkChild {
@Link value: number
build() {
Column() {
Text(`双向绑定: ${this.value}`)
Button('子组件修改')
.onClick(() => {
this.value++ // 会同步回父组件
})
}
}
}
@Entry
@Component
struct LinkParent {
@State parentValue: number = 100
build() {
Column() {
Text(`父组件: ${this.parentValue}`)
Button('父组件修改')
.onClick(() => {
this.parentValue++
})
// 使用 $ 语法传递引用
LinkChild({ value: $parentValue })
}
}
}提示
@Link 不能在 @Entry 装饰的组件中使用,且禁止本地初始化。
@Provide / @Consume
跨层级双向同步:
@Entry
@Component
struct ProvideParent {
@Provide themeColor: string = '#FF0000'
build() {
Column() {
Text('祖先组件')
.fontColor(this.themeColor)
MiddleComponent()
}
}
}
@Component
struct MiddleComponent {
build() {
Column() {
Text('中间组件')
DeepChild()
}
}
}
@Component
struct DeepChild {
@Consume themeColor: string
build() {
Column() {
Text('深层子组件')
.fontColor(this.themeColor)
Button('修改主题色')
.onClick(() => {
this.themeColor = '#00FF00'
})
}
}
}绑定方式:
| 方式 | 语法 |
|---|---|
| 同名绑定 | @Provide color: string + @Consume color: string |
| 别名绑定 | @Provide('theme') color: string + @Consume('theme') c: string |
@Observed / @ObjectLink
嵌套对象属性变化观察:
@Observed
class Book {
title: string
constructor(title: string) {
this.title = title
}
}
@Observed
class Bag {
book: Book
constructor(book: Book) {
this.book = book
}
}
@Component
struct BookCard {
@ObjectLink book: Book
build() {
Column() {
Text(`书名: ${this.book.title}`)
Button('修改书名')
.onClick(() => {
this.book.title = '新书名'
})
}
}
}
@Entry
@Component
struct ObservedDemo {
@State bag: Bag = new Bag(new Book('旧书名'))
build() {
Column() {
BookCard({ book: this.bag.book })
}
}
}注意
@ObjectLink 装饰的变量是只读的,不能被赋值(this.obj = newObj 会报错),但可以修改属性。
UI 构建装饰器
@Builder
自定义构建函数,复用 UI 片段:
// 全局 Builder
@Builder
function GlobalHeader(title: string) {
Row() {
Text(title)
.fontSize(20)
.fontWeight(FontWeight.Bold)
}
.width('100%')
.height(50)
.backgroundColor('#F1F3F5')
}
@Entry
@Component
struct BuilderDemo {
@State title: string = '页面标题'
// 局部 Builder
@Builder
CustomFooter() {
Row() {
Text('底部内容')
}
.width('100%')
.height(60)
}
build() {
Column() {
GlobalHeader(this.title)
Text('页面内容')
this.CustomFooter()
}
}
}参数传递规则:
| 传递方式 | 说明 |
|---|---|
| 按值传递 | 默认方式,状态变化不触发 Builder 刷新 |
| 按引用传递 | 传入对象字面量,状态变化触发刷新 |
class Params {
text: string = ''
}
@Builder
function ReferenceBuilder($$: Params) {
Text($$.text)
}
// 按引用传递
ReferenceBuilder({ text: this.message })@Extend
扩展原生组件样式:
@Extend(Text)
function fancyText(size: number, color: ResourceColor) {
.fontSize(size)
.fontColor(color)
.fontWeight(FontWeight.Bold)
}
@Entry
@Component
struct ExtendDemo {
build() {
Column() {
Text('普通文本')
Text('样式扩展文本').fancyText(24, Color.Red)
}
}
}提示
@Extend 仅支持全局定义,不支持在组件内部定义。
@Styles
通用样式复用:
// 全局 Styles
@Styles
function globalCard() {
.width('90%')
.padding(16)
.backgroundColor(Color.White)
.borderRadius(12)
}
@Entry
@Component
struct StylesDemo {
@State heightValue: number = 100
// 组件内 Styles
@Styles
dynamicStyle() {
.height(this.heightValue)
.backgroundColor(Color.Yellow)
.onClick(() => {
this.heightValue = 200
})
}
build() {
Column() {
Text('全局样式')
.globalCard()
Text('动态样式')
.dynamicStyle()
}
}
}注意
@Styles 不能有参数,仅支持通用属性和通用事件。
@CustomDialog
自定义弹窗:
@CustomDialog
struct CustomAlert {
@Prop title: string
@Prop message: string
controller: CustomDialogController
build() {
Column() {
Text(this.title)
.fontSize(20)
.fontWeight(FontWeight.Bold)
Text(this.message)
.margin(10)
Button('确定')
.onClick(() => {
this.controller.close()
})
}
.padding(20)
.backgroundColor(Color.White)
.borderRadius(16)
}
}
@Entry
@Component
struct DialogDemo {
dialogController: CustomDialogController = new CustomDialogController({
builder: CustomAlert({
title: '提示',
message: '这是一个自定义弹窗'
})
})
build() {
Column() {
Button('显示弹窗')
.onClick(() => {
this.dialogController.open()
})
}
}
}其他装饰器
@Watch
监听状态变量变化:
@Entry
@Component
struct WatchDemo {
@State @Watch('onCountChanged') count: number = 0
@State message: string = ''
onCountChanged(propName: string): void {
this.message = `计数变化为: ${this.count}`
console.info(`属性 ${propName} 发生变化`)
}
build() {
Column() {
Text(this.message)
Text(`计数: ${this.count}`)
Button('增加')
.onClick(() => {
this.count++
})
}
}
}提示
@Watch 在初始化时不会触发,仅在状态变量后续变化时触发。
@Track
属性级精确更新:
class LogTrack {
@Track logInfo: string = ''
owner: string = ''
id: number = 0
}
@Entry
@Component
struct TrackDemo {
@State log: LogTrack = new LogTrack()
build() {
Column() {
// 仅当 logInfo 变化时刷新
Text(this.log.logInfo)
Button('修改 logInfo')
.onClick(() => {
this.log.logInfo = '新日志'
})
// owner 未被 @Track 装饰,不能在 UI 中使用
}
}
}注意
如果类中使用了 @Track,则非 @Track 装饰的属性不能在 UI 中使用,否则运行时报错。
@Trace
深度观测(配合 V2 装饰器使用):
@ObservedV2
class Info {
@Trace name: string = ''
@Trace age: number = 0
}
@ComponentV2
struct TraceDemo {
@Local info: Info = { name: 'Tom', age: 25 }
build() {
Column() {
Text(`${this.info.name}, ${this.info.age}`)
Button('修改')
.onClick(() => {
this.info.name = 'Jerry'
})
}
}
}模块系统
导出 Export
// utils.ets
// 命名导出
export function add(a: number, b: number): number {
return a + b
}
export class Calculator {
multiply(a: number, b: number): number {
return a * b
}
}
export const PI: number = 3.14159
// 默认导出
export default function greet(name: string): string {
return `Hello, ${name}!`
}导入 Import
// 命名导入
import { add, Calculator, PI } from './utils'
// 默认导入
import greet from './utils'
// 混合导入
import greet, { add, Calculator } from './utils'
// 整体导入
import * as Utils from './utils'
// 使用
const sum = add(1, 2)
const calc = new Calculator()
const product = calc.multiply(3, 4)
console.info(Utils.PI)
// 动态导入
async function loadModule() {
const module = await import('./utils')
module.add(1, 2)
}命名空间
// 定义命名空间
namespace Validation {
export interface StringValidator {
isValid(s: string): boolean
}
export class EmailValidator implements StringValidator {
isValid(s: string): boolean {
return s.includes('@')
}
}
const numberRegexp = /^[0-9]+$/
export class ZipCodeValidator implements StringValidator {
isValid(s: string): boolean {
return s.length === 5 && numberRegexp.test(s)
}
}
}
// 使用命名空间
let emailValidator = new Validation.EmailValidator()
console.info(emailValidator.isValid('test@example.com')) // true异步编程
Promise
// 创建 Promise
function fetchData(): Promise<string> {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('数据加载完成')
}, 1000)
})
}
// Promise 链式调用
fetchData()
.then(data => {
console.info(data)
return '下一步'
})
.then(result => {
console.info(result)
})
.catch(error => {
console.error('错误:', error)
})
.finally(() => {
console.info('无论成功失败都执行')
})
// Promise 静态方法
let p1 = Promise.resolve(42)
let p2 = Promise.reject('错误')
Promise.all([p1, fetchData()])
.then(results => {
console.info(results) // [42, '数据加载完成']
})
Promise.race([p1, p2])
.then(result => {
console.info(result)
})async/await
// 定义异步函数
async function loadUserData(): Promise<string> {
let data = await fetchData()
return `用户: ${data}`
}
// 使用 try/catch 处理错误
async function load() {
try {
const result = await loadUserData()
console.info(result)
} catch (error) {
console.error('加载失败:', error)
}
}
// 并行执行
async function loadMultiple() {
const [users, posts] = await Promise.all([
fetchUsers(),
fetchPosts()
])
console.info('全部加载完成')
}
// 辅助函数
async function fetchUsers(): Promise<string[]> {
return ['user1', 'user2']
}
async function fetchPosts(): Promise<string[]> {
return ['post1', 'post2']
}并发任务 TaskPool
TaskPool 用于执行耗时计算任务,避免阻塞 UI 线程:
import { taskpool } from '@kit.ArkTS'
// 定义并发任务函数
@Concurrent
function calculateSum(a: number, b: number): number {
return a + b
}
@Concurrent
function heavyComputation(n: number): number {
let sum = 0
for (let i = 0; i < n; i++) {
sum += i
}
return sum
}
@Entry
@Component
struct TaskPoolDemo {
@State result: string = ''
async executeTask() {
// 创建任务
let task: taskpool.Task = new taskpool.Task(calculateSum, 10, 20)
// 执行任务
let result = await taskpool.execute(task) as number
this.result = `计算结果: ${result}`
}
async executeHeavyTask() {
let task = new taskpool.Task(heavyComputation, 1000000)
let result = await taskpool.execute(task) as number
this.result = `大数计算结果: ${result}`
}
build() {
Column() {
Text(this.result)
Button('执行简单任务')
.onClick(() => this.executeTask())
Button('执行耗时任务')
.onClick(() => this.executeHeavyTask())
}
}
}Worker 多线程
Worker 用于长时间运行的后台任务:
// worker.ts
import { worker } from '@kit.ArkTS'
let parentPort = worker.workerPort
parentPort.onmessage = function(e: MessageEvents) {
let data = e.data
// 处理数据
let result = data * 2
parentPort.postMessage(result)
}
// 主线程
import { worker } from '@kit.ArkTS'
@Entry
@Component
struct WorkerDemo {
private myWorker: worker.ThreadWorker = new worker.ThreadWorker('entry/ets/workers/worker.ts')
@State result: string = ''
aboutToAppear() {
this.myWorker.onmessage = (e: MessageEvents) => {
this.result = `Worker 结果: ${e.data}`
}
}
aboutToDisappear() {
this.myWorker.terminate()
}
sendMessage() {
this.myWorker.postMessage(42)
}
build() {
Column() {
Text(this.result)
Button('发送消息给 Worker')
.onClick(() => this.sendMessage())
}
}
}错误处理
try/catch/finally
function riskyOperation(): void {
throw new Error('发生错误')
}
function handleError(): void {
try {
riskyOperation()
console.info('这行不会执行')
} catch (error) {
// 捕获错误
if (error instanceof Error) {
console.error('错误信息:', error.message)
console.error('错误堆栈:', error.stack)
}
} finally {
// 无论是否发生错误都会执行
console.info('清理资源')
}
}
// 在 async 函数中使用
try {
let result = await fetchData()
} catch (error) {
console.error('异步操作失败:', error)
}自定义错误类型
class ValidationError extends Error {
constructor(message: string) {
super(message)
this.name = 'ValidationError'
}
}
class NetworkError extends Error {
statusCode: number
constructor(message: string, statusCode: number) {
super(message)
this.name = 'NetworkError'
this.statusCode = statusCode
}
}
function validateAge(age: number): void {
if (age < 0) {
throw new ValidationError('年龄不能为负数')
}
if (age > 150) {
throw new ValidationError('年龄不合法')
}
}
// 使用
try {
validateAge(-5)
} catch (error) {
if (error instanceof ValidationError) {
console.error('验证错误:', error.message)
}
}错误处理最佳实践
// 可选链和空值合并
let userName = user?.profile?.name ?? '匿名用户'
// 类型守卫
function processValue(value: string | number | null): void {
if (value === null) {
console.info('值为 null')
return
}
if (typeof value === 'string') {
console.info('字符串:', value.toUpperCase())
} else {
console.info('数字:', value.toFixed(2))
}
}ArkTS 与 TypeScript 差异总结
| 特性 | TypeScript | ArkTS |
|---|---|---|
any 类型 | 允许 | 禁止 |
| 动态属性 | 允许 obj.newProp = 1 | 禁止 |
eval() | 允许 | 禁止 |
new Function() | 允许 | 禁止 |
| 声明式 UI | 不支持 | @Component + build() |
| 状态管理 | 不支持 | @State, @Prop, @Link 等 |
| 并发模型 | 单线程 | TaskPool + Worker |
| 装饰器 | 实验性 | 核心特性 |
| 类型推断 | 宽松 | 严格,必须显式声明 |
| Sendable 对象 | 不支持 | 支持跨线程共享 |
| 文件扩展名 | .ts | .ets |
// TypeScript 允许,ArkTS 禁止
let dynamic: any = 1
dynamic = 'string'
let obj = {}
obj['newKey'] = 'value'
eval('console.info("hello")')
// ArkTS 正确写法
let strict: number = 1
interface MyObject {
newKey: string
}
let obj2: MyObject = { newKey: 'value' }最佳实践
- 始终显式声明类型:不要依赖类型推断,提高代码可读性
- 使用接口定义数据结构:比类更轻量,适合数据契约
- 避免使用
any:会失去类型检查的保护 - 合理使用枚举:替代魔法数字,提高代码可维护性
- 异步操作使用 async/await:代码更清晰,错误处理更方便
- 状态管理选择合适的装饰器:
- 组件内部状态 ->
@State - 父传子单向 ->
@Prop - 父子双向 ->
@Link - 跨层级共享 ->
@Provide/@Consume - 嵌套对象观察 ->
@Observed/@ObjectLink
- 组件内部状态 ->
- 耗时操作放入 TaskPool:避免阻塞 UI 主线程
- 使用
@Track优化性能:精确控制属性级更新,避免冗余刷新