声明式UI语法
基本概念
-
装饰器:用于装饰类、结构、方法及变量,并赋予其特殊的含义。
例如:
@Entry 有该装饰器的自定义组件,可以在UIAbility中使用,作为页面入口。该装饰器配合@Component装饰器使用
@Component 自定义组件
@State 表示组件中的状态变量,状态变化会出发UI刷新。
-
UI描述:以声明式的方式来描述UI的结构,在组件的build方法中。
-
自定义组件:可复用的UI单元,可组合其他组件。
-
系统组件:ArkUI框架中默认内置的基础和容器组件。例如:Column、Row、Text、Image、Button等。
-
属性方法:ArkTs中,使用链式调用的方式来配置组件属性。
-
事件方法:事件响应逻辑,也是使用链式调用的方式,设置如onclick方法等,在方法内部进行实现。
基础的组件一般就是由上述部分组成,如下图:
当然,也有一些其他的语法范式方便我们进行封装复用,如:
除此之外,ArkTS扩展了多种语法范式来使开发更加便捷:
-
@Builder/@BuilderParam:特殊的封装UI描述的方法,细粒度的封装和复用UI描述。
-
@Extend/@Styles:扩展内置组件和封装属性样式,更灵活地组合内置组件。
-
stateStyles:多态样式,可以依据组件的内部状态的不同,设置不同样式。
这些后续会讲到。
声明式UI描述
创建组件
在ArkTs的基础语法中,我们讲到类,实例化一个类,需要使用new
关键字进行。而在UI组件中,创建组件是不需要使用new
关键字的。
无参数
如果组件的接口定义没有包含必选的构造参数,则组件后面的()
中可以不配置任何内容。
例如Button()
Text()
等包含可选参数的组件,Driver()
等没有构造参数的组件。
有参数
如果组件的接口定义中包含了必选构造参数,则在组件后的()
中需要配置相应的参数。
例如Image()
组件,必选参数为src。
变量和表达式也可以用作参数赋值。
配置属性
组件的属性方法以.
链式调用的方式配置样式和其他属性。
Text(this.message)
.id('HelloWorld')
.fontSize(50)
.fontWeight(FontWeight.Bold)
.alignRules({
center: { anchor: '__container__', align: VerticalAlign.Center },
middle: { anchor: '__container__', align: HorizontalAlign.Center }
})
配置事件
使用箭头函数配置组件的事件方法
Button() {
Text('跳转')
.fontSize(30)
.fontWeight(FontWeight.Bold)
}
.type(ButtonType.Capsule)
.margin({ top: '0.00vp', right: '0.00vp', bottom: '150.00vp', left: '0.00vp' })
.backgroundColor('#ff0000')
.width('50%')
.height('10%')
.alignRules({
center: { anchor: '__container__', align: VerticalAlign.Bottom },
middle: { anchor: '__container__', align: HorizontalAlign.Center }
})
.onClick(() => {
console.info('click second button')
router.pushUrl({ url: 'pages/Second' }).then(() => {
console.info('jump success')
}).catch((err: BusinessError) => {
console.error(`jump failed,errCode:${err.code},errMessage:${err.message}`)
})
})
}
.height('100%')
.width('100%')
如需使用组件中的成员函数配置组件的事件方法,需要使用bind this。
myClickHandler(): void {
this.counter += 2;
}
...
Button('add counter')
.onClick(this.myClickHandler.bind(this))
ArkTs语法不推荐使用成员函数配合bind(this)的方式去配置组件的事件方法
使用声明的箭头函数,可以直接调用,不需要使用bind(this)
fn = () => {
console.info(`counter: ${this.counter}`)
this.counter++
}
...
Button('add counter')
.onClick(this.fn)
配置子组件
如果组件是容器组件,则支持子组件配置,需要在组件声明后,紧随的闭包中添加子组件的描述。如Column
Row
List
等组件。
RelativeContainer() {
Text(this.message)
.id('SecondHelloWorld')
.fontSize(50)
.fontWeight(FontWeight.Bold)
.alignRules({
center: { anchor: '__container__', align: VerticalAlign.Center },
middle: { anchor: '__container__', align: HorizontalAlign.Center }
})
Button() {
Text('back')
.fontSize('30')
.fontWeight(FontWeight.Bold)
}
.type(ButtonType.Capsule)
.margin({
bottom: 50
})
.alignRules({
center: { anchor: '__container__', align: VerticalAlign.Bottom },
middle: { anchor: '__container__', align: HorizontalAlign.Center }
})
.width('50%')
.height('10%')
.backgroundColor('#ff0000')
.onClick(() => {
try {
router.back()
} catch (err) {
let code = (err as BusinessError).code
let message = (err as BusinessError).message
console.info(`jump error:${code},${message}`)
}
})
}
.height('100%')
.width('100%')