赞
踩
基于:HarmonyOS开发者3.1/4.0版本配套的开发者文档,对应API能力级别为API 9 Release
ARkTS以声明方式组合和扩展组件来描述应用程序的UI,还提供了基本的属性、事件、子组件配置方法
创建组件包含有参数和无参数两种方式(具体根据组件的构造方法)
如果组件的接口定义没有包含必选构造参数,则组件后面的()
不需要配置任何内容,如:
Column() {
Text('item 1')
Divider()
Text('item 2')
}
如果组件的接口定义包含构造参数,可以在组件后面的()
配置相应参数:
// string类型的参数
Text('test')
// $r形式引入应用资源,可应用于多语言场景
Text($r('app.string.title_value'))
// 无参数形式
Text()
// 变量或表达式也可以用于参数赋值,表达式返回的结果类型必须满足参数类型要求
Text(`count: ${this.count}`)
属性方法以.
链式调用的方式配置系统组件的样式和其他属性,建议每个属性方法单独写一行
// 配置Text组件字体的大小
Text('test')
.fontSize(12)
// 配置组件的多个属性,还可以传入变量或者表达式
Image('test.jpg')
.alt('error.jpg')
.width(this.count % 2 === 0 ? 100 : 200)
.height(this.offset + 100)
// 对于一些系统组件,ArkUI还为其预定义了一些枚举类型供调用
Text('hello')
.fontSize(20)
.fontColor(Color.Red)
.fontWeight(FontWeight.Bold)
事件方法以.
链式调用的方式配置系统组件支持的事件,建议每个事件方法单独写一行
// 使用剪头函数配置组件的事件方法 Button('Click me') .onClick(() => { this.myText = 'ArkUI'; }) // 使用匿名函数,要求使用bind,以确保函数中的this指向当前组件 Button('add counter') .onClick(function(){ this.counter += 2; }.bind(this)) // 使用组件成员函数 myClickHandler(): void { this.counter += 2; } ... Button('add counter') .onClick(this.myClickHandler.bind(this))
如果组件支持子组件配置,则需要再尾随闭包{...}
中为组件添加子组件的UI描述(组件嵌套)
Column() {
Text('Hello')
.fontSize(100)
Divider()
Text(this.myText)
.fontSize(100)
.fontColor(Color.Red)
}
自定义组件具有以下特点:
成员函数/变量
成员函数具有以下约束:
自定义组件的成员变量有以下约束:
@Component struct MyComponent { private countDownFrom: number = 0; private color: Color = Color.Blue; build() { } } @Entry @Component struct ParentComponent { private someColor: Color = Color.Pink; build() { Column() { // 创建MyComponent实例,并将创建MyComponent成员变量countDownFrom初始化为10,将成员变量color初始化为this.someColor MyComponent({ countDownFrom: 10, color: this.someColor }) } } }
build()函数
所有声明在build函数的语言,统称为UI描述语言,需要遵循:
自定义组件通过“.”链式调用的形式设置通用样式
设置样式时并不是直接设置给自定义组件的,相当于给自定义组件套一个不可见的容器,样式被设置给这个容器
页面生命周期如下:
组件生命周期:
自定义组件的创建和渲染流程
第4步会保存两个map:
自定义组件的重新渲染
当事件句柄被触发改变了状态变量时,或者LocalStorage / AppStorage中的属性更改,并导致绑定的状态量更改其值时:
自定义组件的删除
如果if组件的分支改变,或者ForEach循环渲染中数组的个数改变,组件将被删除:
ArkUI还提供了更轻量化的UI元素复用机制@Builder,被@Builder修饰的函数遵循build函数语法规则,开发者可将简单的UI元素抽象成一个方法,在build中调用
@Builder修饰的函数也叫自定义构建函数
自定义组件内自定义构建函数
定义的语法:
@Builder MyBuilderFunction({ ... })
使用方法:
this.MyBuilderFunction({ ... })
全局自定义构建函数
定义的语法:
@Builder function MyGlobalBuilderFunction({ ... })
使用方法:
MyGlobalBuilderFunction()
参数传递规则
自定义构建函数的参数传递有按值传递和按引用传递两种方式,需要遵循以下规则:
按引用传递参数
传递的参数可以为状态变量,且状态变量的改变会引起@Builder方法内的UI刷新,传递方式为$$
@Builder function ABuilder($$: { paramA1: string }) { Row() { Text(`UseStateVarByReference: ${$$.paramA1} `) } } @Entry @Component struct Parent { @State label: string = 'Hello'; build() { Column() { // 在Parent组件中调用ABuilder的时候,将this.label引用传递给ABuilder ABuilder({ paramA1: this.label }) Button('Click me').onClick(() => { // 点击“Click me”后,UI从“Hello”刷新为“ArkUI” this.label = 'ArkUI'; }) } } }
按值传递参数
传递的参数发生变化时,不会引起@Builder内UI刷新
@Builder function ABuilder(paramA1: string) {
Row() {
Text(`UseStateVarByValue: ${paramA1} `)
}
}
@Entry
@Component
struct Parent {
label: string = 'Hello';
build() {
Column() {
ABuilder(this.label)
}
}
}
简单理解:按值传递相当于一次性调用构造函数,按引用传递相当于绑定
当开发者创建了自定义组件,并想对该组件添加特定功能时,比如添加一个点击跳转操作。如果直接在组件内嵌入方法,那么所有引用这个组件的页面就都添加了这个功能,这可能不是开发者想要的。ArkUI引入了@BuilderParam装饰器,来装饰指向@Builder方法的变量,类似于slot占位符,在指定位置加入自己想要的东西,并且不会影响其他使用这个组件的地方。
初始化@BuilderParam装饰的方法
@BuilderParam装饰的方法只能被自定义构建函数初始化
使用所属自定义组件的自定义构建函数或者全局的自定义构建函数,在本地初始化@BuilderParam
@Builder function GlobalBuilder0() {}
@Component
struct Child {
@Builder doNothingBuilder() {};
@BuilderParam aBuilder0: () => void = this.doNothingBuilder;
@BuilderParam aBuilder1: () => void = GlobalBuilder0;
build(){}
}
用父组件自定义构建函数初始化子组件@BuilderParam装饰的方法
@Component struct Child { @BuilderParam aBuilder0: () => void; build() { Column() { this.aBuilder0() } } } @Entry @Component struct Parent { @Builder componentBuilder() { Text(`Parent builder `) } build() { Column() { Child({ aBuilder0: this.componentBuilder }) } } }
显示效果如下图:
这里官方文档没有说明,但是子组件定义slot的时候,给出的样例中,给slot赋值了一个默认的空构造器,猜测slot需要空构造器来占位,当父组件不指定该slot的时候,渲染过程中实际调用了空构造函数,而不是没渲染这个slot。
在开发中,需要注意this指向正确。
在自定义组件中使用@BuilderParam装饰的属性时也可通过尾随闭包进行初始化。在初始化自定义组件时,组件后紧跟一个大括号“{}”形成尾随闭包场景。(其实可以理解为定义一个匿名函数,当做参数传递给slot)
// xxx.ets @Component struct CustomContainer { @Prop header: string; @BuilderParam closer: () => void build() { Column() { Text(this.header) .fontSize(30) this.closer() } } } @Builder function specificParam(label1: string, label2: string) { Column() { Text(label1) .fontSize(30) Text(label2) .fontSize(30) } } @Entry @Component struct CustomContainerUser { @State text: string = 'header'; build() { Column() { // 创建CustomContainer,在创建CustomContainer时,通过其后紧跟一个大括号“{}”形成尾随闭包 // 作为传递给子组件CustomContainer @BuilderParam closer: () => void的参数 CustomContainer({ header: this.text }) { Column() { specificParam('testA', 'testB') }.backgroundColor(Color.Yellow) .onClick(() => { this.text = 'changeHeader'; }) } } } }
效果如下(点击黄色区域,会改变标题为‘changeHeader’):
提供了提炼公共样式进行复用的装饰器@Styles。
@Styles装饰器可以将多条样式设置提炼成一个方法,直接在组件声明的位置调用。
当前@Styles仅支持通用属性和通用事件
@Styles不支持参数
@Styles可以定义在组件内或全局,在全局定义时需在方法名前面添加function关键字,组件内定义时则不需要添加function关键字
// 全局
@Styles function functionName() { ... }
// 在组件内
@Component
struct FancyUse {
@Styles fancy() {
.height(100)
}
}
定义在组件内的@Styles可以通过this访问组件的常量和状态变量,并可以在@Styles里通过事件来改变状态变量的值
组件内的@Styles的优先级高于全局@Styles
在@Styles的基础上,提供了@Extend,用于扩展原生组件的样式。
@Extend(UIComponentName) function functionName { ... }
使用规则
和@Styles不同,@Extend仅支持定义在全局,不支持组件内部定义
和@Styles不同,@Extend支持封装指定的组件的私有属性和私有事件和预定义相同组件的@Extend方法
// @Extend(Text)可以支持Text的私有属性fontColor
@Extend(Text) function fancy () {
.fontColor(Color.Red)
}
// superFancyText可以调用预定义的fancy
@Extend(Text) function superFancyText(size:number) {
.fontSize(size)
.fancy()
}
和@Styles不同,@Extend装饰的方法支持参数,开发者可以在调用时传递参数,需要遵循TS方法传值调用
@Extend装饰的方法的参数可以作为function,作为Event事件的句柄
@Extend(Text) function makeMeClick(onClick: () => void) { .backgroundColor(Color.Blue) .onClick(onClick) } @Entry @Component struct FancyUse { @State label: string = 'Hello World'; onClickHandler() { this.label = 'Hello ArkUI'; } build() { Row({ space: 10 }) { Text(`${this.label}`) .makeMeClick(this.onClickHandler.bind(this)) } } }
@Extend的参数可以作为状态变量,当状态变量改变时,UI可以正常的被刷新渲染
@Styles和@Extend仅仅应用于静态页面的样式复用,是stateStyles可以依据组件的内部状态的不同,快速的设置不同样式。
stateStyles是属性方法,可以根据UI内部状态来设置样式,类似于css伪类,但语法不同。ArkUI提供四种状态:
@Entry @Component struct MyComponent { @Styles normalStyle() { .backgroundColor(Color.Gray) } @Styles pressedStyle() { .backgroundColor(Color.Red) } build() { Column() { Text('Text1') .fontSize(50) .fontColor(Color.White) .stateStyles({ normal: this.normalStyle, pressed: this.pressedStyle, }) } } }
@Entry @Component struct CompWithInlineStateStyles { @State focusedColor: Color = Color.Red; normalColor: Color = Color.Green build() { Column() { Button('clickMe').height(100).width(100) .stateStyles({ normal: { .backgroundColor(this.normalColor) }, focused: { .backgroundColor(this.focusedColor) } }) .onClick(() => { this.focusedColor = Color.Pink }) .margin('30%') } } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。