-
-
鸿蒙HarmonyOS实战-ArkTS语言(渲染控制)
-
发表于: 2024-4-2 23:05 2436
-
????前言
编程语言中都有自己基本的控制结构,它们在程序设计中起到了非常重要的作用。以下是几个原因:
分支控制: 在程序执行过程中,有时需要根据不同的条件分支来执行不同的代码逻辑。if/else结构通过判断条件来决定程序如何执行,实现了程序的分支控制。
数据迭代: 在程序中,需要对一些数据进行遍历、操作或者计算。ForEach和LazyForEach提供了一种便捷的方法,可以针对数据集合进行遍历,并对其中的每个元素执行特定操作。
**惰性计算: **在某些情况下,程序中需要对大量的数据进行遍历或计算。LazyForEach可以实现惰性计算,只在需要时才计算相应的结果,避免了程序在运行时不必要的计算,从而提高程序效率。
????一、ArkTS语言渲染控制
ArkTS是一种基于TypeScript的编程语言,支持对渲染过程进行控制和调整。以下是ArkTS语言中实现渲染控制的三个关键组件:
if/else:if/else结构可以用于根据条件控制是否渲染某些元素。例如,可以通过if/else语句来实现某些物体在特定场景或条件下的显示或隐藏。
ForEach:ForEach是一个迭代方法,能够遍历数组、对象等数据结构中的元素,并在渲染过程中对它们进行控制。例如,可以使用ForEach在场景中定位并控制多个物体的位置、尺寸、颜色等属性。
LazyForEach:与普通ForEach不同,LazyForEach是一个惰性迭代方法,它只在需要迭代数据时才进行计算。这使得LazyForEach在处理大型数据集时更加高效,可以减少渲染时间和资源占用。
通过这些关键组件,ArkTS语言可以实现灵活、高效的渲染控制,帮助开发人员实现各种复杂的渲染效果和场景呈现。
1.if/else:条件渲染
????1.1 变化规则
If/else是一种在程序中用于控制流程的结构。它包括一个if语句和一个可选的else语句。if语句表示如果条件成立,那么就执行一段代码,否则跳过该代码;else语句表示如果条件不成立,那么就执行另一段代码。这种结构允许程序根据不同的条件执行不同的操作,从而实现更灵活的程序控制。
????1.2 使用场景
☀️1.2.1 使用if进行条件渲染
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 | @Entry @Component struct ViewA { @State count: number = 0 ; build() { Column() { Text(`count = ${this.count}`) if (this.count > 0 ) { Text(`count is positive`) .fontColor(Color.Green) } Button( 'increase count' ) .onClick(() = > { this.count + + ; }) Button( 'decrease count' ) .onClick(() = > { this.count - - ; }) } } } |
☀️1.2.2 使用if/else进行条件渲染
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 | @Component struct CounterView { @Link counter: number; label: string = 'unknown' ; build() { Row() { Text(`${this.label}`) Button(`counter ${this.counter} + 1 `) .onClick(() = > { this.counter + = 1 ; }) } } } @Entry @Component struct MainView { @State toggle: boolean = true; @State counter: number = 0 ; build() { Column() { if (this.toggle) { CounterView({ counter: $counter, label: 'CounterView #positive' }) } else { CounterView({ counter: $counter, label: 'CounterView #negative' }) } Button(`toggle ${this.toggle}`) .onClick(() = > { this.toggle = !this.toggle; }) } } } |
☀️1.2.3 嵌套if语句
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 | @Entry @Component struct CompA { @State toggle: boolean = false; @State toggleColor: boolean = false; build() { Column() { Text( 'Before' ) .fontSize( 15 ) if (this.toggle) { Text( 'Top True, positive 1 top' ) .backgroundColor( '#aaffaa' ).fontSize( 20 ) / / 内部 if 语句 if (this.toggleColor) { Text( 'Top True, Nested True, positive COLOR Nested ' ) .backgroundColor( '#00aaaa' ).fontSize( 15 ) } else { Text( 'Top True, Nested False, Negative COLOR Nested ' ) .backgroundColor( '#aaaaff' ).fontSize( 15 ) } } else { Text( 'Top false, negative top level' ).fontSize( 20 ) .backgroundColor( '#ffaaaa' ) if (this.toggleColor) { Text( 'positive COLOR Nested ' ) .backgroundColor( '#00aaaa' ).fontSize( 15 ) } else { Text( 'Negative COLOR Nested ' ) .backgroundColor( '#aaaaff' ).fontSize( 15 ) } } Text( 'After' ) .fontSize( 15 ) Button( 'Toggle Outer' ) .onClick(() = > { this.toggle = !this.toggle; }) Button( 'Toggle Inner' ) .onClick(() = > { this.toggleColor = !this.toggleColor; }) } } } |
2.ForEach:循环渲染
????2.1 变化规则
ForEach是一个数组方法,用于执行一些操作,例如对数组中的每个元素执行一些代码,或者将每个元素转换为新的数组。它可以接收一个回调函数作为参数,该函数将在数组的每个元素上执行一次。在每次调用回调函数时,都会向其传递当前元素的值、索引和整个数组。该方法不会更改原始数组,而是返回一个新的、由回调函数返回的数组。
更多鸿蒙最新技术知识点,请关注作者博客:https://t.doruo.cn/14DjR1rEY
ForEach接口描述:
1 2 3 4 5 | ForEach( arr: Array, itemGenerator: (item: Array, index?: number) = > void, keyGenerator?: (item: Array, index?: number): string = > string ) |
注意点keyGenerator为键值生成函数,可以达到去重的效果:
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 | @Entry @Component struct Parent { @State simpleList: Array<string> = [ 'one' , 'two' , 'two' , 'three' ]; build() { Row() { Column() { ForEach(this.simpleList, (item: string) = > { ChildItem({ item: item }) }, (item: string) = > item) } .width( '100%' ) .height( '100%' ) } .height( '100%' ) .backgroundColor( 0xF1F3F5 ) } } @Component struct ChildItem { @Prop item: string; build() { Text(this.item) .fontSize( 50 ) } } |
执行结果
????2.2 使用场景
☀️2.2.1 数据源不变
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 | @Entry @Component struct ArticleList { @State simpleList: Array<number> = [ 1 , 2 , 3 , 4 , 5 ]; build() { Column() { ForEach(this.simpleList, (item: string) = > { ArticleSkeletonView() .margin({ top: 20 }) }, (item: string) = > item) } .padding( 20 ) .width( '100%' ) .height( '100%' ) } } @Builder function textArea(width: number | Resource | string = '100%' , height: number | Resource | string = '100%' ) { Row() .width(width) .height(height) .backgroundColor( '#FFF2F3F4' ) } @Component struct ArticleSkeletonView { build() { Row() { Column() { textArea( 80 , 80 ) } .margin({ right: 20 }) Column() { textArea( '60%' , 20 ) textArea( '50%' , 20 ) } .alignItems(HorizontalAlign.Start) .justifyContent(FlexAlign.SpaceAround) .height( '100%' ) } .padding( 20 ) .borderRadius( 12 ) .backgroundColor( '#FFECECEC' ) .height( 120 ) .width( '100%' ) .justifyContent(FlexAlign.SpaceBetween) } } |
执行效果:
☀️2.2.2 数据源数组项发生变化
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 | @Entry @Component struct ArticleListView { @State isListReachEnd: boolean = false; @State articleList: Array<Article> = [ new Article( '001' , '第1篇文章' , '文章简介内容' ), new Article( '002' , '第2篇文章' , '文章简介内容' ), new Article( '003' , '第3篇文章' , '文章简介内容' ), new Article( '004' , '第4篇文章' , '文章简介内容' ), new Article( '005' , '第5篇文章' , '文章简介内容' ), new Article( '006' , '第6篇文章' , '文章简介内容' ) ] loadMoreArticles() { this.articleList.push(new Article( '007' , '加载的新文章' , '文章简介内容' )); } build() { Column({ space: 5 }) { List () { ForEach(this.articleList, (item: Article) = > { ListItem() { ArticleCard({ article: item }) .margin({ top: 20 }) } }, (item: Article) = > item. id ) } .onReachEnd(() = > { this.isListReachEnd = true; }) .parallelGesture( PanGesture({ direction: PanDirection.Up, distance: 80 }) .onActionStart(() = > { if (this.isListReachEnd) { this.loadMoreArticles(); this.isListReachEnd = false; } }) ) .padding( 20 ) .scrollBar(BarState.Off) } .width( '100%' ) .height( '100%' ) .backgroundColor( 0xF1F3F5 ) } } @Component struct ArticleCard { @Prop article: Article; build() { Row() { Image($r( 'app.media.icon' )) .width( 80 ) .height( 80 ) .margin({ right: 20 }) Column() { Text(this.article.title) .fontSize( 20 ) .margin({ bottom: 8 }) Text(this.article.brief) .fontSize( 16 ) .fontColor(Color.Gray) .margin({ bottom: 8 }) } .alignItems(HorizontalAlign.Start) .width( '80%' ) .height( '100%' ) } .padding( 20 ) .borderRadius( 12 ) .backgroundColor( '#FFECECEC' ) .height( 120 ) .width( '100%' ) .justifyContent(FlexAlign.SpaceBetween) } } |
当列表滚动到底部时,如果手势滑动距离超过指定的80,将触发loadMoreArticle()函数。此函数会在articleList数据源的尾部添加一个新的数据项,从而增加数据源的长度。
执行效果:
☀️2.2.3 数据源数组项子属性变化
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 | @Entry @Component struct ArticleListView { @State articleList: Array<Article> = [ new Article( '001' , '第0篇文章' , '文章简介内容' , false, 100 ), new Article( '002' , '第1篇文章' , '文章简介内容' , false, 100 ), new Article( '003' , '第2篇文章' , '文章简介内容' , false, 100 ), new Article( '004' , '第4篇文章' , '文章简介内容' , false, 100 ), new Article( '005' , '第5篇文章' , '文章简介内容' , false, 100 ), new Article( '006' , '第6篇文章' , '文章简介内容' , false, 100 ), ]; build() { List () { ForEach(this.articleList, (item: Article) = > { ListItem() { ArticleCard({ article: item }) .margin({ top: 20 }) } }, (item: Article) = > item. id ) } .padding( 20 ) .scrollBar(BarState.Off) .backgroundColor( 0xF1F3F5 ) } } @Component struct ArticleCard { @ObjectLink article: Article; handleLiked() { this.article.isLiked = !this.article.isLiked; this.article.likesCount = this.article.isLiked ? this.article.likesCount + 1 : this.article.likesCount - 1 ; } build() { Row() { Image($r( 'app.media.icon' )) .width( 80 ) .height( 80 ) .margin({ right: 20 }) Column() { Text(this.article.title) .fontSize( 20 ) .margin({ bottom: 8 }) Text(this.article.brief) .fontSize( 16 ) .fontColor(Color.Gray) .margin({ bottom: 8 }) Row() { Image(this.article.isLiked ? $r( 'app.media.iconLiked' ) : $r( 'app.media.iconUnLiked' )) .width( 24 ) .height( 24 ) .margin({ right: 8 }) Text(this.article.likesCount.toString()) .fontSize( 16 ) } .onClick(() = > this.handleLiked()) .justifyContent(FlexAlign.Center) } .alignItems(HorizontalAlign.Start) .width( '80%' ) .height( '100%' ) } .padding( 20 ) .borderRadius( 12 ) .backgroundColor( '#FFECECEC' ) .height( 120 ) .width( '100%' ) .justifyContent(FlexAlign.SpaceBetween) } } |
执行结果:
== 注意:开发者在使用ForEach时应特别重视keyGenerator为键值生成函数,会根据键值生成函数确定替换的值。==
3.LazyForEach:数据懒加载
????3.1 变化规则
LazyForEach是一种延迟执行的迭代方法,它可以帮助我们更高效地遍历和操作数组。与常规的ForEach方法不同,LazyForEach方法不会立即执行回调函数,而是在需要访问数组元素时才将回调函数应用于该元素。这种延迟执行的方式可以大大减少不必要的计算,提高代码性能。LazyForEach在处理大型数组或频繁进行迭代时特别有用。
更多鸿蒙最新技术知识点,请关注作者博客:https://t.doruo.cn/14DjR1rEY
LazyForEach接口描述:
1 2 3 4 5 | LazyForEach( dataSource: IDataSource, / / 需要进行数据迭代的数据源 itemGenerator: (item: any , index?: number) = > void, / / 子组件生成函数 keyGenerator?: (item: any , index?: number) = > string / / 键值生成函数 ): void |
IDataSource接口描述:
1 2 3 4 5 6 | interface IDataSource { totalCount(): number; / / 获得数据总数 getData(index: number): Object ; / / 获取索引值对应的数据 registerDataChangeListener(listener: DataChangeListener): void; / / 注册数据改变的监听器 unregisterDataChangeListener(listener: DataChangeListener): void; / / 注销数据改变的监听器 } |
DataChangeListener接口描述:
1 2 3 4 5 6 7 8 9 10 11 | interface DataChangeListener { onDataReloaded(): void; / / 重新加载数据时调用 onDataAdded(index: number): void; / / 添加数据时调用 onDataMoved( from : number, to: number): void; / / 数据移动起始位置与数据移动目标位置交换时调用 onDataDeleted(index: number): void; / / 删除数据时调用 onDataChanged(index: number): void; / / 改变数据时调用 onDataAdd(index: number): void; / / 添加数据时调用 onDataMove( from : number, to: number): void; / / 数据移动起始位置与数据移动目标位置交换时调用 onDataDelete(index: number): void; / / 删除数据时调用 onDataChange(index: number): void; / / 改变数据时调用 } |
????3.2 使用场景
☀️3.2.1 首次渲染
3.2.1.1 生成不同键值
1、正常渲染
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 | / / Basic implementation of IDataSource to handle data listener class BasicDataSource implements IDataSource { private listeners: DataChangeListener[] = []; private originDataArray: string[] = []; public totalCount(): number { return 0 ; } public getData(index: number): string { return this.originDataArray[index]; } / / 该方法为框架侧调用,为LazyForEach组件向其数据源处添加listener监听 registerDataChangeListener(listener: DataChangeListener): void { if (this.listeners.indexOf(listener) < 0 ) { console.info( 'add listener' ); this.listeners.push(listener); } } / / 该方法为框架侧调用,为对应的LazyForEach组件在数据源处去除listener监听 unregisterDataChangeListener(listener: DataChangeListener): void { const pos = this.listeners.indexOf(listener); if (pos > = 0 ) { console.info( 'remove listener' ); this.listeners.splice(pos, 1 ); } } / / 通知LazyForEach组件需要重载所有子组件 notifyDataReload(): void { this.listeners.forEach(listener = > { listener.onDataReloaded(); }) } / / 通知LazyForEach组件需要在index对应索引处添加子组件 notifyDataAdd(index: number): void { this.listeners.forEach(listener = > { listener.onDataAdd(index); }) } / / 通知LazyForEach组件在index对应索引处数据有变化,需要重建该子组件 notifyDataChange(index: number): void { this.listeners.forEach(listener = > { listener.onDataChange(index); }) } / / 通知LazyForEach组件需要在index对应索引处删除该子组件 notifyDataDelete(index: number): void { this.listeners.forEach(listener = > { listener.onDataDelete(index); }) } } class MyDataSource extends BasicDataSource { private dataArray: string[] = []; public totalCount(): number { return this.dataArray.length; } public getData(index: number): string { return this.dataArray[index]; } public addData(index: number, data: string): void { this.dataArray.splice(index, 0 , data); this.notifyDataAdd(index); } public pushData(data: string): void { this.dataArray.push(data); this.notifyDataAdd(this.dataArray.length - 1 ); } } @Entry @Component struct MyComponent { private data: MyDataSource = new MyDataSource(); aboutToAppear() { for (let i = 0 ; i < = 20 ; i + + ) { this.data.pushData(`Hello ${i}`) } } build() { List ({ space: 3 }) { LazyForEach(this.data, (item: string) = > { ListItem() { Row() { Text(item).fontSize( 50 ) .onAppear(() = > { console.info( "appear:" + item) }) }.margin({ left: 10 , right: 10 }) } }, (item: string) = > item) }.cachedCount( 5 ) } } |
2、键值相同时错误渲染
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 | class BasicDataSource implements IDataSource { private listeners: DataChangeListener[] = []; private originDataArray: string[] = []; public totalCount(): number { return 0 ; } public getData(index: number): string { return this.originDataArray[index]; } registerDataChangeListener(listener: DataChangeListener): void { if (this.listeners.indexOf(listener) < 0 ) { console.info( 'add listener' ); this.listeners.push(listener); } } unregisterDataChangeListener(listener: DataChangeListener): void { const pos = this.listeners.indexOf(listener); if (pos > = 0 ) { console.info( 'remove listener' ); this.listeners.splice(pos, 1 ); } } notifyDataReload(): void { this.listeners.forEach(listener = > { listener.onDataReloaded(); }) } notifyDataAdd(index: number): void { this.listeners.forEach(listener = > { listener.onDataAdd(index); }) } notifyDataChange(index: number): void { this.listeners.forEach(listener = > { listener.onDataChange(index); }) } notifyDataDelete(index: number): void { this.listeners.forEach(listener = > { listener.onDataDelete(index); }) } } class MyDataSource extends BasicDataSource { private dataArray: string[] = []; public totalCount(): number { return this.dataArray.length; } public getData(index: number): string { return this.dataArray[index]; } public addData(index: number, data: string): void { this.dataArray.splice(index, 0 , data); this.notifyDataAdd(index); } public pushData(data: string): void { this.dataArray.push(data); this.notifyDataAdd(this.dataArray.length - 1 ); } } @Entry @Component struct MyComponent { private data: MyDataSource = new MyDataSource(); aboutToAppear() { for (let i = 0 ; i < = 20 ; i + + ) { this.data.pushData(`Hello ${i}`) } } build() { List ({ space: 3 }) { LazyForEach(this.data, (item: string) = > { ListItem() { Row() { Text(item).fontSize( 50 ) .onAppear(() = > { console.info( "appear:" + item) }) }.margin({ left: 10 , right: 10 }) } }, (item: string) = > 'same key' ) }.cachedCount( 5 ) } } |
☀️3.2.2 非首次渲染
3.2.2.1 添加数据
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 | class BasicDataSource implements IDataSource { private listeners: DataChangeListener[] = []; private originDataArray: string[] = []; public totalCount(): number { return 0 ; } public getData(index: number): string { return this.originDataArray[index]; } registerDataChangeListener(listener: DataChangeListener): void { if (this.listeners.indexOf(listener) < 0 ) { console.info( 'add listener' ); this.listeners.push(listener); } } unregisterDataChangeListener(listener: DataChangeListener): void { const pos = this.listeners.indexOf(listener); if (pos > = 0 ) { console.info( 'remove listener' ); this.listeners.splice(pos, 1 ); } } notifyDataReload(): void { this.listeners.forEach(listener = > { listener.onDataReloaded(); }) } notifyDataAdd(index: number): void { this.listeners.forEach(listener = > { listener.onDataAdd(index); }) } notifyDataChange(index: number): void { this.listeners.forEach(listener = > { listener.onDataChange(index); }) } notifyDataDelete(index: number): void { this.listeners.forEach(listener = > { listener.onDataDelete(index); }) } } class MyDataSource extends BasicDataSource { private dataArray: string[] = []; public totalCount(): number { return this.dataArray.length; } public getData(index: number): string { return this.dataArray[index]; } public addData(index: number, data: string): void { this.dataArray.splice(index, 0 , data); this.notifyDataAdd(index); } public pushData(data: string): void { this.dataArray.push(data); this.notifyDataAdd(this.dataArray.length - 1 ); } } @Entry @Component struct MyComponent { private data: MyDataSource = new MyDataSource(); aboutToAppear() { for (let i = 0 ; i < = 20 ; i + + ) { this.data.pushData(`Hello ${i}`) } } build() { List ({ space: 3 }) { LazyForEach(this.data, (item: string) = > { ListItem() { Row() { Text(item).fontSize( 50 ) .onAppear(() = > { console.info( "appear:" + item) }) }.margin({ left: 10 , right: 10 }) } .onClick(() = > { / / 点击追加子组件 this.data.pushData(`Hello ${this.data.totalCount()}`); }) }, (item: string) = > item) }.cachedCount( 5 ) } } |
3.2.2.2 删除数据
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 | class BasicDataSource implements IDataSource { private listeners: DataChangeListener[] = []; private originDataArray: string[] = []; public totalCount(): number { return 0 ; } public getData(index: number): string { return this.originDataArray[index]; } registerDataChangeListener(listener: DataChangeListener): void { if (this.listeners.indexOf(listener) < 0 ) { console.info( 'add listener' ); this.listeners.push(listener); } } unregisterDataChangeListener(listener: DataChangeListener): void { const pos = this.listeners.indexOf(listener); if (pos > = 0 ) { console.info( 'remove listener' ); this.listeners.splice(pos, 1 ); } } notifyDataReload(): void { this.listeners.forEach(listener = > { listener.onDataReloaded(); }) } notifyDataAdd(index: number): void { this.listeners.forEach(listener = > { listener.onDataAdd(index); }) } notifyDataChange(index: number): void { this.listeners.forEach(listener = > { listener.onDataChange(index); }) } notifyDataDelete(index: number): void { this.listeners.forEach(listener = > { listener.onDataDelete(index); }) } } class MyDataSource extends BasicDataSource { dataArray: string[] = []; public totalCount(): number { return this.dataArray.length; } public getData(index: number): string { return this.dataArray[index]; } public addData(index: number, data: string): void { this.dataArray.splice(index, 0 , data); this.notifyDataAdd(index); } public pushData(data: string): void { this.dataArray.push(data); this.notifyDataAdd(this.dataArray.length - 1 ); } public deleteData(index: number): void { this.dataArray.splice(index, 1 ); this.notifyDataDelete(index); } } @Entry @Component struct MyComponent { private data: MyDataSource = new MyDataSource(); aboutToAppear() { for (let i = 0 ; i < = 20 ; i + + ) { this.data.pushData(`Hello ${i}`) } } build() { List ({ space: 3 }) { LazyForEach(this.data, (item: string, index: number) = > { ListItem() { Row() { Text(item).fontSize( 50 ) .onAppear(() = > { console.info( "appear:" + item) }) }.margin({ left: 10 , right: 10 }) } .onClick(() = > { / / 点击删除子组件 this.data.deleteData(this.data.dataArray.indexOf(item)); }) }, (item: string) = > item) }.cachedCount( 5 ) } } |
3.2.2.3 改变单个数据
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 113 | class BasicDataSource implements IDataSource { private listeners: DataChangeListener[] = []; private originDataArray: string[] = []; public totalCount(): number { return 0 ; } public getData(index: number): string { return this.originDataArray[index]; } registerDataChangeListener(listener: DataChangeListener): void { if (this.listeners.indexOf(listener) < 0 ) { console.info( 'add listener' ); this.listeners.push(listener); } } unregisterDataChangeListener(listener: DataChangeListener): void { const pos = this.listeners.indexOf(listener); if (pos > = 0 ) { console.info( 'remove listener' ); this.listeners.splice(pos, 1 ); } } notifyDataReload(): void { this.listeners.forEach(listener = > { listener.onDataReloaded(); }) } notifyDataAdd(index: number): void { this.listeners.forEach(listener = > { listener.onDataAdd(index); }) } notifyDataChange(index: number): void { this.listeners.forEach(listener = > { listener.onDataChange(index); }) } notifyDataDelete(index: number): void { this.listeners.forEach(listener = > { listener.onDataDelete(index); }) } } class MyDataSource extends BasicDataSource { private dataArray: string[] = []; public totalCount(): number { return this.dataArray.length; } public getData(index: number): string { return this.dataArray[index]; } public addData(index: number, data: string): void { this.dataArray.splice(index, 0 , data); this.notifyDataAdd(index); } public pushData(data: string): void { this.dataArray.push(data); this.notifyDataAdd(this.dataArray.length - 1 ); } public deleteData(index: number): void { this.dataArray.splice(index, 1 ); this.notifyDataDelete(index); } public changeData(index: number, data: string): void { this.dataArray.splice(index, 0 , data); this.notifyDataChange(index); } } @Entry @Component struct MyComponent { private moved: number[] = []; private data: MyDataSource = new MyDataSource(); aboutToAppear() { for (let i = 0 ; i < = 20 ; i + + ) { this.data.pushData(`Hello ${i}`) } } build() { List ({ space: 3 }) { LazyForEach(this.data, (item: string, index: number) = > { ListItem() { Row() { Text(item).fontSize( 50 ) .onAppear(() = > { console.info( "appear:" + item) }) }.margin({ left: 10 , right: 10 }) } .onClick(() = > { this.data.changeData(index, item + '00' ); }) }, (item: string) = > item) }.cachedCount( 5 ) } } |
3.2.2.4 改变多个数据
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 113 114 115 116 117 118 119 120 121 122 123 124 | class BasicDataSource implements IDataSource { private listeners: DataChangeListener[] = []; private originDataArray: string[] = []; public totalCount(): number { return 0 ; } public getData(index: number): string { return this.originDataArray[index]; } registerDataChangeListener(listener: DataChangeListener): void { if (this.listeners.indexOf(listener) < 0 ) { console.info( 'add listener' ); this.listeners.push(listener); } } unregisterDataChangeListener(listener: DataChangeListener): void { const pos = this.listeners.indexOf(listener); if (pos > = 0 ) { console.info( 'remove listener' ); this.listeners.splice(pos, 1 ); } } notifyDataReload(): void { this.listeners.forEach(listener = > { listener.onDataReloaded(); }) } notifyDataAdd(index: number): void { this.listeners.forEach(listener = > { listener.onDataAdd(index); }) } notifyDataChange(index: number): void { this.listeners.forEach(listener = > { listener.onDataChange(index); }) } notifyDataDelete(index: number): void { this.listeners.forEach(listener = > { listener.onDataDelete(index); }) } } class MyDataSource extends BasicDataSource { private dataArray: string[] = []; public totalCount(): number { return this.dataArray.length; } public getData(index: number): string { return this.dataArray[index]; } public addData(index: number, data: string): void { this.dataArray.splice(index, 0 , data); this.notifyDataAdd(index); } public pushData(data: string): void { this.dataArray.push(data); this.notifyDataAdd(this.dataArray.length - 1 ); } public deleteData(index: number): void { this.dataArray.splice(index, 1 ); this.notifyDataDelete(index); } public changeData(index: number): void { this.notifyDataChange(index); } public reloadData(): void { this.notifyDataReload(); } public modifyAllData(): void { this.dataArray = this.dataArray. map ((item: string) = > { return item + '0' ; }) } } @Entry @Component struct MyComponent { private moved: number[] = []; private data: MyDataSource = new MyDataSource(); aboutToAppear() { for (let i = 0 ; i < = 20 ; i + + ) { this.data.pushData(`Hello ${i}`) } } build() { List ({ space: 3 }) { LazyForEach(this.data, (item: string, index: number) = > { ListItem() { Row() { Text(item).fontSize( 50 ) .onAppear(() = > { console.info( "appear:" + item) }) }.margin({ left: 10 , right: 10 }) } .onClick(() = > { this.data.modifyAllData(); this.data.reloadData(); }) }, (item: string) = > item) }.cachedCount( 5 ) } } |
3.2.2.5 改变数据子属性
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 113 114 115 116 117 118 119 | class BasicDataSource implements IDataSource { private listeners: DataChangeListener[] = []; private originDataArray: StringData[] = []; public totalCount(): number { return 0 ; } public getData(index: number): StringData { return this.originDataArray[index]; } registerDataChangeListener(listener: DataChangeListener): void { if (this.listeners.indexOf(listener) < 0 ) { console.info( 'add listener' ); this.listeners.push(listener); } } unregisterDataChangeListener(listener: DataChangeListener): void { const pos = this.listeners.indexOf(listener); if (pos > = 0 ) { console.info( 'remove listener' ); this.listeners.splice(pos, 1 ); } } notifyDataReload(): void { this.listeners.forEach(listener = > { listener.onDataReloaded(); }) } notifyDataAdd(index: number): void { this.listeners.forEach(listener = > { listener.onDataAdd(index); }) } notifyDataChange(index: number): void { this.listeners.forEach(listener = > { listener.onDataChange(index); }) } notifyDataDelete(index: number): void { this.listeners.forEach(listener = > { listener.onDataDelete(index); }) } } class MyDataSource extends BasicDataSource { private dataArray: StringData[] = []; public totalCount(): number { return this.dataArray.length; } public getData(index: number): StringData { return this.dataArray[index]; } public addData(index: number, data: StringData): void { this.dataArray.splice(index, 0 , data); this.notifyDataAdd(index); } public pushData(data: StringData): void { this.dataArray.push(data); this.notifyDataAdd(this.dataArray.length - 1 ); } } @Observed class StringData { message: string; constructor(message: string) { this.message = message; } } @Entry @Component struct MyComponent { private moved: number[] = []; @State data: MyDataSource = new MyDataSource(); aboutToAppear() { for (let i = 0 ; i < = 20 ; i + + ) { this.data.pushData(new StringData(`Hello ${i}`)); } } build() { List ({ space: 3 }) { LazyForEach(this.data, (item: StringData, index: number) = > { ListItem() { ChildComponent({data: item}) } .onClick(() = > { item.message + = '0' ; }) }, (item: StringData, index: number) = > index.toString()) }.cachedCount( 5 ) } } @Component struct ChildComponent { @ObjectLink data: StringData build() { Row() { Text(this.data.message).fontSize( 50 ) .onAppear(() = > { console.info( "appear:" + this.data.message) }) }.margin({ left: 10 , right: 10 }) } } |
☀️3.2.3 问题点
3.2.3.1 索引重置
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 113 114 115 | class BasicDataSource implements IDataSource { private listeners: DataChangeListener[] = []; private originDataArray: string[] = []; public totalCount(): number { return 0 ; } public getData(index: number): string { return this.originDataArray[index]; } registerDataChangeListener(listener: DataChangeListener): void { if (this.listeners.indexOf(listener) < 0 ) { console.info( 'add listener' ); this.listeners.push(listener); } } unregisterDataChangeListener(listener: DataChangeListener): void { const pos = this.listeners.indexOf(listener); if (pos > = 0 ) { console.info( 'remove listener' ); this.listeners.splice(pos, 1 ); } } notifyDataReload(): void { this.listeners.forEach(listener = > { listener.onDataReloaded(); }) } notifyDataAdd(index: number): void { this.listeners.forEach(listener = > { listener.onDataAdd(index); }) } notifyDataChange(index: number): void { this.listeners.forEach(listener = > { listener.onDataChange(index); }) } notifyDataDelete(index: number): void { this.listeners.forEach(listener = > { listener.onDataDelete(index); }) } } class MyDataSource extends BasicDataSource { private dataArray: string[] = []; public totalCount(): number { return this.dataArray.length; } public getData(index: number): string { return this.dataArray[index]; } public addData(index: number, data: string): void { this.dataArray.splice(index, 0 , data); this.notifyDataAdd(index); } public pushData(data: string): void { this.dataArray.push(data); this.notifyDataAdd(this.dataArray.length - 1 ); } public deleteData(index: number): void { this.dataArray.splice(index, 1 ); this.notifyDataDelete(index); } public reloadData(): void { this.notifyDataReload(); } } @Entry @Component struct MyComponent { private data: MyDataSource = new MyDataSource(); aboutToAppear() { for (let i = 0 ; i < = 20 ; i + + ) { this.data.pushData(`Hello ${i}`) } } build() { List ({ space: 3 }) { LazyForEach(this.data, (item: string, index: number) = > { ListItem() { Row() { Text(item).fontSize( 50 ) .onAppear(() = > { console.info( "appear:" + item) }) }.margin({ left: 10 , right: 10 }) } .onClick(() = > { / / 点击删除子组件 this.data.deleteData(index); / / 重置所有子组件的index索引 this.data.reloadData(); }) }, (item: string, index: number) = > item + index.toString()) }.cachedCount( 5 ) } } |
3.2.3.2 图片闪烁
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 113 114 115 116 117 118 119 120 121 122 123 | class BasicDataSource implements IDataSource { private listeners: DataChangeListener[] = []; private originDataArray: StringData[] = []; public totalCount(): number { return 0 ; } public getData(index: number): StringData { return this.originDataArray[index]; } registerDataChangeListener(listener: DataChangeListener): void { if (this.listeners.indexOf(listener) < 0 ) { console.info( 'add listener' ); this.listeners.push(listener); } } unregisterDataChangeListener(listener: DataChangeListener): void { const pos = this.listeners.indexOf(listener); if (pos > = 0 ) { console.info( 'remove listener' ); this.listeners.splice(pos, 1 ); } } notifyDataReload(): void { this.listeners.forEach(listener = > { listener.onDataReloaded(); }) } notifyDataAdd(index: number): void { this.listeners.forEach(listener = > { listener.onDataAdd(index); }) } notifyDataChange(index: number): void { this.listeners.forEach(listener = > { listener.onDataChange(index); }) } notifyDataDelete(index: number): void { this.listeners.forEach(listener = > { listener.onDataDelete(index); }) } } class MyDataSource extends BasicDataSource { private dataArray: StringData[] = []; public totalCount(): number { return this.dataArray.length; } public getData(index: number): StringData { return this.dataArray[index]; } public addData(index: number, data: StringData): void { this.dataArray.splice(index, 0 , data); this.notifyDataAdd(index); } public pushData(data: StringData): void { this.dataArray.push(data); this.notifyDataAdd(this.dataArray.length - 1 ); } } @Observed class StringData { message: string; imgSrc: Resource; constructor(message: string, imgSrc: Resource) { this.message = message; this.imgSrc = imgSrc; } } @Entry @Component struct MyComponent { @State data: MyDataSource = new MyDataSource(); aboutToAppear() { for (let i = 0 ; i < = 20 ; i + + ) { this.data.pushData(new StringData(`Hello ${i}`, $r( 'app.media.img' ))); } } build() { List ({ space: 3 }) { LazyForEach(this.data, (item: StringData, index: number) = > { ListItem() { ChildComponent({data: item}) } .onClick(() = > { item.message + = '0' ; }) }, (item: StringData, index: number) = > index.toString()) }.cachedCount( 5 ) } } @Component struct ChildComponent { @ObjectLink data: StringData build() { Column() { Text(this.data.message).fontSize( 50 ) .onAppear(() = > { console.info( "appear:" + this.data.message) }) Image(this.data.imgSrc) .width( 500 ) .height( 200 ) }.margin({ left: 10 , right: 10 }) } } |
3.2.3.3 ObjectLink属性变化后UI更新
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 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | class BasicDataSource implements IDataSource { private listeners: DataChangeListener[] = []; private originDataArray: StringData[] = []; public totalCount(): number { return 0 ; } public getData(index: number): StringData { return this.originDataArray[index]; } registerDataChangeListener(listener: DataChangeListener): void { if (this.listeners.indexOf(listener) < 0 ) { console.info( 'add listener' ); this.listeners.push(listener); } } unregisterDataChangeListener(listener: DataChangeListener): void { const pos = this.listeners.indexOf(listener); if (pos > = 0 ) { console.info( 'remove listener' ); this.listeners.splice(pos, 1 ); } } notifyDataReload(): void { this.listeners.forEach(listener = > { listener.onDataReloaded(); }) } notifyDataAdd(index: number): void { this.listeners.forEach(listener = > { listener.onDataAdd(index); }) } notifyDataChange(index: number): void { this.listeners.forEach(listener = > { listener.onDataChange(index); }) } notifyDataDelete(index: number): void { this.listeners.forEach(listener = > { listener.onDataDelete(index); }) } } class MyDataSource extends BasicDataSource { private dataArray: StringData[] = []; public totalCount(): number { return this.dataArray.length; } public getData(index: number): StringData { return this.dataArray[index]; } public addData(index: number, data: StringData): void { this.dataArray.splice(index, 0 , data); this.notifyDataAdd(index); } public pushData(data: StringData): void { this.dataArray.push(data); this.notifyDataAdd(this.dataArray.length - 1 ); } } @Observed class StringData { message: NestedString; constructor(message: NestedString) { this.message = message; } } @Observed class NestedString { message: string; constructor(message: string) { this.message = message; } } @Entry @Component struct MyComponent { private moved: number[] = []; @State data: MyDataSource = new MyDataSource(); aboutToAppear() { for (let i = 0 ; i < = 20 ; i + + ) { this.data.pushData(new StringData(new NestedString(`Hello ${i}`))); } } build() { List ({ space: 3 }) { LazyForEach(this.data, (item: StringData, index: number) = > { ListItem() { ChildComponent({data: item}) } .onClick(() = > { item.message = new NestedString(item.message.message + '0' ); }) }, (item: StringData, index: number) = > item.toString() + index.toString()) }.cachedCount( 5 ) } } @Component struct ChildComponent { @ObjectLink data: StringData build() { Row() { Text(this.data.message.message).fontSize( 50 ) .onAppear(() = > { console.info( "appear:" + this.data.message.message) }) }.margin({ left: 10 , right: 10 }) } } |
看完三件事❤️
- 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我四个小忙:
- 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
- 关注公众号 『 蜀道衫 』,不定期分享原创知识。
- 同时可以期待后续文章ing????
- 关注后回复【666】扫码即可获取鸿蒙学习资料包
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课