2.4:渲染控制语法
ArkUI开发框架是一套构建 HarmonyOS / OpenHarmony 应用界面的声明式UI开发框架,它支持程序使用 if/else
条件渲染, ForEach
循环渲染以及 LazyForEach
懒加载渲染。本节笔者介绍一下这三种渲染方式的使用。
2.4.1:if/else条件渲染
使用 if/else
进行条件渲染需要注意以下情况:
2.4.2:ForEach循环渲染
ArkUI开发框架提供循环渲染(ForEach组件)来迭代数组,并为每个数组项创建相应的组件。
ForEach
定义如下:
interface ForEach {(
arr: Array<any>,
itemGenerator: (item: any, index?: number) => void,
keyGenerator?: (item: any, index?: number) => string
): ForEach;
}
1
2
3
4
5
6
arr:必须是数组,允许空数组,空数组场景下不会创建子组件。
itemGenerator:子组件生成函数,为给定数组项生成一个或多个子组件。
keyGenerator:匿名参数,用于给定数组项生成唯一且稳定的键值。
简单样例如下所示:
@Entry @Component struct ComponentTest {
private textArray: string[] = ["1", "2", "3", "4", "5"];
build() {
Column({space: 10}) {
ForEach(this.textArray, (item: string, index?: number) => {
Text(`Text: ${item}`)
.fontSize(20)
.backgroundColor(Color.Pink)
.margin({ top: 10 })
})
}
.width('100%')
.height('100%')
.padding(10)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Entry @Component class MyView {
var textArray: Array<String> = ["1", "2", "3", "4", "5"];
func build() {
Column(10) {
ForEach(this.textArray, itemGeneratorFunc: { item: String, index: Int64 =>
Text("Text: ${item}")
.fontSize(20)
.backgroundColor(0xffc0cb)
.margin(top: 10)
})
}
.width(100.percent)
.height(100.percent)
.padding(10)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
样例运行结果如下图所示:
2.4.3:LazyForEach循环渲染
ArkUI开发框架提供数据懒加载( LazyForEach
组件)从提供的数据源中按需迭代数据,并在每次迭代过程中创建相应的组件。
LazyForEach
定义如下:
interface LazyForEach {(
dataSource: IDataSource,
itemGenerator: (item: any, index?: number) => void,
keyGenerator?: (item: any, index?: number) => string
): LazyForEach;
}
export declare interface IDataSource {
totalCount(): number;
getData(index: number): any;
registerDataChangeListener(listener: DataChangeListener): void;
unregisterDataChangeListener(listener: DataChangeListener): void;
}
export declare interface DataChangeListener {
onDataReloaded(): void;
onDataAdded(index: number): void;
onDataMoved(from: number, to: number): void;
onDataDeleted(index:number): void;
onDataChanged(index:number): void;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
- itemGenerator:子组件生成函数,为给定数组项生成一个或多个子组件。
- keyGenerator:匿名参数,用于给定数组项生成唯一且稳定的键值。
- dataSource:实现
IDataSource
接口的对象,需要开发者实现相关接口。
IDataSource
定义如下:
export declare interface IDataSource {
totalCount(): number;
getData(index: number): any;
registerDataChangeListener(listener: DataChangeListener): void;
unregisterDataChangeListener(listener: DataChangeListener): void;
}
1
2
3
4
5
6
- totalCount:获取数据总数。
- getData:获取索引对应的数据。
- registerDataChangeListener:注册改变数据的监听器。
- unregisterDataChangeListener:注销改变数据的监听器。
DataChangeListener
定义如下:
export declare interface DataChangeListener {
onDataReloaded(): void;
onDataAdded(index: number): void;
onDataMoved(from: number, to: number): void;
onDataDeleted(index:number): void;
onDataChanged(index:number): void;
}
1
2
3
4
5
6
7
- onDataReloaded:item重新加载数据时的回调。
- onDataAdded:item新添加数据时的回调。
- onDataMoved:item数据移动时的回调。
- onDataDeleted:item数据删除时的回调。
- onDataChanged:item数据变化时的回调。
简单样例如下:
class Student {
public sid: number;
public name: string;
public age: number
public address: string
public avatar: string
constructor(sid: number = -1, name: string, age: number = 16, address: string = '北京', avatar: string = "") {
this.sid = sid;
this.name = name;
this.age = age;
this.address = address;
this.avatar = avatar;
}
}
abstract class BaseDataSource<T> implements IDataSource {
private mDataSource: T[] = new Array();
constructor(dataList: T[]) {
this.mDataSource = dataList;
}
totalCount(): number {
return this.mDataSource == null ? 0 : this.mDataSource.length
}
getData(index: number): T|null {
return index >= 0 && index < this.totalCount() ? this.mDataSource[index] : null;
}
registerDataChangeListener(listener: DataChangeListener) {
}
unregisterDataChangeListener(listener: DataChangeListener) {
}
}
class StudentDataSource extends BaseDataSource<Student> {
constructor(students: Student[]) {
super(students)
}
}
function mock(): Student[] {
let students: Array<Student> = [];
for(let i = 0; i < 20; i++) {
students[i] = new Student(i, "student:" + i, i + 10, "address:" + i, "app.media.test")
}
return students;
}
@Entry @Component struct ComponentTest {
private student: Student[] = mock();
private dataSource: StudentDataSource = new StudentDataSource(this.student);
build() {
Column({space: 10}) {
List() {
LazyForEach(this.dataSource, (item: Student) => {
ListItem() {
Row() {
Image($r("app.media.test"))
.height('100%')
.width(80)
Column() {
Text(this.getName(item))
.fontSize(20)
Text('address: ' + item.address)
.fontSize(17)
}
.margin({left: 5})
.alignItems(HorizontalAlign.Start)
.layoutWeight(1)
}
.width('100%')
.height('100%')
}
.width('100%')
.height(60)
})
}
.divider({
strokeWidth: 3,
color: Color.Gray
})
.width('90%')
.height(160)
.backgroundColor(Color.Pink)
}
.width('100%')
.height('100%')
.padding(10)
}
getName(item: Student): string {
console.log("index: " + item.sid);
return 'index:' + item.sid + ", " + item.name;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package ohos_app_cangjie_entry
import ohos.base.*
import ohos.component.*
import ohos.state_manage.*
import ohos.state_macro_manage.*
import ohos.webview.*
import std.time.*
import std.collection.*
import ohos.prompt_action.*
import std.sync.*
import ohos.concurrency.*
public class Student {
public Student(let sid: Int, let name: String, let age: Int, let address: String, let avator: String) {
}
}
public class StudentDataSource <: IDataSource<Student> {
public StudentDataSource(let dataSource!: ArrayList<Student> = ArrayList<Student>()) {}
public var callback: Option<DataChangeListener> = None
public func totalCount(): Int64 {
return this.dataSource.size
}
public func getData(index: Int64): Student {
return this.dataSource[index]
}
public func onRegisterDataChangeListener(listener: DataChangeListener): Unit {
this.callback = listener
}
public func onUnregisterDataChangeListener(listener: DataChangeListener): Unit {
this.callback = None
}
public func notifyDataSetChanged(): Unit {
let listener = this.callback.getOrThrow()
listener.onDataReloaded()
}
}
func mock(): ArrayList<Student> {
let list = ArrayList<Student>()
for (index in 0..50) {
list.append(Student(index, "name: ${index}", index, "address: ${index}", "avator: ${index}"))
}
return list
}
let students: ArrayList<Student> = mock()
let studentDataSource: StudentDataSource = StudentDataSource(dataSource: students)
@Entry @Component class MyView {
func build() {
Column(10) {
List() {
LazyForEach(studentDataSource, itemGeneratorFunc: { item: Student, index: Int =>
ListItem() {
Row() {
Image(@r(app.media.test))
.height(100.percent)
.width(80)
Column() {
Text(this.getName(item))
.fontSize(20)
Text("address: ${item.address}")
.fontSize(17)
}
.margin(left: 5)
.alignItems(HorizontalAlign.Start)
.layoutWeight(1)
}
.width(100.percent)
.height(100.percent)
}
.width(100.percent)
.height(60)
})
}
.divider(
strokeWidth: 3.vp,
color: Color(0xdddddd)
)
.width(90.percent)
.height(160)
.backgroundColor(0xffc0cb)
}
.width(100.percent)
.height(100.percent)
.padding(10)
}
func getName(item: Student): String {
return "index: ${item.sid}, ${item.name}"
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
样例运行结果如下图所示:
打印结果如下:
[phone][Console INFO] 04/02 23:54:19 82919424 app Log: Application onCreate
[phone][Console DEBUG] 04/02 23:54:19 82919424 app Log: index: 0
[phone][Console DEBUG] 04/02 23:54:19 82919424 app Log: index: 1
[phone][Console DEBUG] 04/02 23:54:19 82919424 app Log: index: 2
[phone][Console DEBUG] 04/02 23:54:19 82919424 app Log: index: 3
[phone][Console DEBUG] 04/02 23:54:19 82919424 app Log: index: 4
[phone][Console DEBUG] 04/02 23:54:19 82919424 app Log: index: 5
1
2
3
4
5
6
7
📢:使用懒加载,可以有效的降低资源占用
2.4.4:小结
本节主要讲解了ArkUI开发框架的渲染控制语法,读者熟练掌握后可以随心所欲的控制页面的显示逻辑了(#^.^#)
(adsbygoogle = window.adsbygoogle || []).push({});