ArkTS声明式开发范式:
规范中各个内容说明如下:
- 装饰器
1、基本UI装饰器@Entry、@Component
@Entry
装饰struct,页面的入口。
@Component
装饰struct,表示该struct具有基于组件的能力。
2、数据装饰器@State、@Prop、@Link
@State
当数据被修改时,所在组件的build()方法会被重新调用,进而重新绘制该页面UI。此装饰器的作用范围仅限于其所在的UI内部。
@Prop
该组件继承@State的基本功能,同时,又有两个新的特点:
- 只能被其父控件的@State变量初始化(假设为name)
- 与其父组件建立单向联系,监听父组件中的变量name,当name的值发生变化时,该@Prop也会同步变化,进而重绘制其所在控件的UI。
@Link
与@Prop不同的是,@Link会与其父控件中对应的@State变化建立双向联系,即当子组件中的@Link对象发生变化时,其父组件中对应的@State变量也会随之变化,这个时候父UI与子UI都会重绘。
数据装饰器@State、@Prop、@Link三者的相同点与不同点:
相同点:
- 都会引起UI的重绘
- 内部私有
不同点:
不同点 | @State | @Prop | @Link |
装饰内容 | 基本数据类型、类、数组 | 基本数据类型 | 基本数据类型、类、数组 |
关联 | 不与其他控件关联 | 父@State -> 子@Prop单向关联 | 父@State <-> 子@Link单向关联 |
初始化时机 | 声明时 | 创建组件时由参数传入 | 创建组件时由参数传入 |
- 生产者-消费者模式的装饰器@Provide、@Consume
这一对是形成生产者-消费者模式的装饰器,且双向绑定。@Provide必须设置初始值,@Consume不可设置默认初始值。
触发变化的时机:
- 基础类型(boolean、string、number)变量的改变
- @Observed class类型变量以及其属性的修改
- 添加、删除、跟新数组中的元素
struct CompA {
@Provide("reviewVote") reviewVotes: number = 0;
}
struct CompB {
@Consume("reviewVote") reviewVotes: number
}
框架行为:
- 初始渲染:
- @Provide装饰的变量会以map的形式,传递给当前@Provide所属组件的所有子组件;
- 子组件中如果使用@Consume变量,则会在map中查找是否有该变量名/alias(别名)对应的@Provide的变量,如果查找不到,框架会抛出JS ERROR;
- 在初始化@Consume变量时,和@State/@Link的流程类似,@Consume变量会保存在map中查找到的@Provide变量,并把自己注册给@Provide。
- 当@Provide装饰的数据变化时:
- 通过初始渲染的步骤可知,子组件@Consume已把自己注册给父组件。父组件@Provide变量变更后,会遍历更新所有依赖它的系统组件(elementid)和状态变量(@Consume);
- 通知@Consume更新后,子组件所有依赖@Consume的系统组件(elementId)都会被通知更新。以此实现@Provide对@Consume状态数据同步。
- 当@Consume装饰的数据变化时:
- 通过初始渲染的步骤可知,子组件@Consume持有@Provide的实例。在@Consume更新后调用@Provide的更新方法,将更新的数值同步回@Provide,以此实现@Consume向@Provide的同步更新。
- 观察者模式的装饰器@Watch
使用观察者模式的装饰器,但该装饰器不是触发变量变化,而是绑定一个函数,当@Watch变量变化时,调用该函数。
struct ComA {
// 绑定onBasketUpdate方法,当变量更新时调用
@State @Watch('onBasketUpdate') shopBasket: Array = [7, 12, 47, 3]
onBasketUpdate(propName: string): void {
this.updateTotal()
}
}
- 自定义组件
可复用的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的主要扩展。