当前位置:   article > 正文

梅科尔工作室-王柯竣-鸿蒙笔记3_lazyforeach循环渲染可以使用在以下哪些容器组件中( )。

lazyforeach循环渲染可以使用在以下哪些容器组件中( )。

基础知识方面:

由list容器组件和listitem容器组件构成,list是一个大容器,listitem是大容器里的小容器

使用说明

示例

渲染控制:

ArkTS也提供了渲染控制的能力。条件渲染可根据应用的不同状态,渲染对应状态下的UI内容。循环渲染可从数据源中迭代获取数据,并在每次迭代过程中创建相应的组件。

条件渲染:

使用if/else进行条件渲染。

  1. Column() {
  2. if (this.count < 0) {
  3. Text('count is negative').fontSize(14)
  4. } else if (this.count % 2 === 0) {
  5. Text('count is even').fontSize(14)
  6. } else {
  7. Text('count is odd').fontSize(14)
  8. }
  9. }

循环渲染:

通过循环渲染(ForEach)从数组中获取数据,并为每个数据项创建相应的组件,可减少代码复杂度。

  1. ForEach(
  2. arr: any[],
  3. itemGenerator: (item: any, index?: number) => void,
  4. keyGenerator?: (item: any, index?: number) => string
  5. )

参数:

参数名

参数类型

必填

参数描述

arr

any[]

必须是数组,允许设置为空数组,空数组场景下将不会创建子组件。同时允许设置返回值为数组类型的函数,例如arr.slice(1, 3),设置的函数不得改变包括数组本身在内的任何状态变量,如Array.splice、Array.sort或Array.reverse这些改变原数组的函数。

itemGenerator

(item: any, index?: number) => void

生成子组件的lambda函数,为数组中的每一个数据项创建一个或多个子组件,单个子组件或子组件列表必须包括在大括号“{...}”中。

keyGenerator

(item: any, index?: number) => string

匿名函数,用于给数组中的每一个数据项生成唯一且固定的键值。当数据项在数组中的位置更改时,其键值不得更改,当数组中的数据项被新项替换时,被替换项的键值和新项的键值必须不同。键值生成器的功能是可选的,但是,为了使开发框架能够更好地识别数组更改,提高性能,建议提供。如将数组反向时,如果没有提供键值生成器,则ForEach中的所有节点都将重建。

示例:

  1. // xxx.ets
  2. @Entry
  3. @Component
  4. struct MyComponent {
  5. @State arr: number[] = [10, 20, 30]
  6. build() {
  7. Column({ space: 5 }) {
  8. Button('Reverse Array')
  9. .onClick(() => {
  10. this.arr.reverse()
  11. })
  12. ForEach(this.arr, (item: number) => {
  13. Text(`item value: ${item}`).fontSize(18)
  14. Divider().strokeWidth(2)
  15. }, (item: number) => item.toString())
  16. }
  17. }
  18. }

数据懒加载

通过数据懒加载(LazyForEach)从提供的数据源中按需迭代数据,并在每次迭代过程中创建相应的组件。

  1. LazyForEach(
  2. dataSource: IDataSource,
  3. itemGenerator: (item: any) => void,
  4. keyGenerator?: (item: any) => string
  5. ): void
  6. interface IDataSource {
  7. totalCount(): number;
  8. getData(index: number): any;
  9. registerDataChangeListener(listener: DataChangeListener): void;
  10. unregisterDataChangeListener(listener: DataChangeListener): void;
  11. }
  12. interface DataChangeListener {
  13. onDataReloaded(): void;
  14. onDataAdd(index: number): void;
  15. onDataMove(from: number, to: number): void;
  16. onDataDelete(index: number): void;
  17. onDataChange(index: number): void;
  18. }

参数名

参数类型

必填

参数描述

dataSource

IDataSource

实现IDataSource接口的对象,需要开发者实现相关接口。

itemGenerator

(item: any) => void

生成子组件的lambda函数,为数组中的每一个数据项创建一个或多个子组件,单个子组件或子组件列表必须包括在大括号“{...}”中。

keyGenerator

(item: any) => string

匿名函数,用于给数组中的每一个数据项生成唯一且固定的键值。当数据项在数组中的位置更改时,其键值不得更改,当数组中的数据项被新项替换时,被替换项的键值和新项的键值必须不同。键值生成器的功能是可选的,但是,为了使开发框架能够更好地识别数组更改,提高性能,建议提供。如将数组反向时,如果没有提供键值生成器,则LazyForEach中的所有节点都将重建。

IDataSource类型说明

DataChangeListener类型说明

名称

描述

onDataReloaded(): void

重新加载所有数据。

onDataAdded(index: number): void (deprecated)

通知组件index的位置有数据添加。

onDataMoved(from: number, to: number): void (deprecated)

通知组件数据从from的位置移到to的位置。

onDataDeleted(index: number): void (deprecated)

通知组件index的位置有数据删除。

onDataChanged(index: number): void (deprecated)

通知组件index的位置有数据变化。

onDataAdd(index: number): void 8+

通知组件index的位置有数据添加。

onDataMove(from: number, to: number): void 8+

通知组件数据从from的位置移到to的位置。

onDataDelete(index: number): void 8+

通知组件index的位置有数据删除。

onDataChange(index: number): void 8+

通知组件index的位置有数据变化。

示例:

  1. // xxx.ets
  2. class BasicDataSource implements IDataSource {
  3. private listeners: DataChangeListener[] = []
  4. public totalCount(): number {
  5. return 0
  6. }
  7. public getData(index: number): any {
  8. return undefined
  9. }
  10. registerDataChangeListener(listener: DataChangeListener): void {
  11. if (this.listeners.indexOf(listener) < 0) {
  12. console.info('add listener')
  13. this.listeners.push(listener)
  14. }
  15. }
  16. unregisterDataChangeListener(listener: DataChangeListener): void {
  17. const pos = this.listeners.indexOf(listener);
  18. if (pos >= 0) {
  19. console.info('remove listener')
  20. this.listeners.splice(pos, 1)
  21. }
  22. }
  23. notifyDataReload(): void {
  24. this.listeners.forEach(listener => {
  25. listener.onDataReloaded()
  26. })
  27. }
  28. notifyDataAdd(index: number): void {
  29. this.listeners.forEach(listener => {
  30. listener.onDataAdd(index)
  31. })
  32. }
  33. notifyDataChange(index: number): void {
  34. this.listeners.forEach(listener => {
  35. listener.onDataChange(index)
  36. })
  37. }
  38. notifyDataDelete(index: number): void {
  39. this.listeners.forEach(listener => {
  40. listener.onDataDelete(index)
  41. })
  42. }
  43. notifyDataMove(from: number, to: number): void {
  44. this.listeners.forEach(listener => {
  45. listener.onDataMove(from, to)
  46. })
  47. }
  48. }
  49. class MyDataSource extends BasicDataSource {
  50. // 初始化数据列表
  51. private dataArray: string[] = ['/path/image0.png', '/path/image1.png', '/path/image2.png', '/path/image3.png']
  52. public totalCount(): number {
  53. return this.dataArray.length
  54. }
  55. public getData(index: number): any {
  56. return this.dataArray[index]
  57. }
  58. public addData(index: number, data: string): void {
  59. this.dataArray.splice(index, 0, data)
  60. this.notifyDataAdd(index)
  61. }
  62. public pushData(data: string): void {
  63. this.dataArray.push(data)
  64. this.notifyDataAdd(this.dataArray.length - 1)
  65. }
  66. }
  67. @Entry
  68. @Component
  69. struct MyComponent {
  70. private data: MyDataSource = new MyDataSource()
  71. build() {
  72. List({ space: 3 }) {
  73. LazyForEach(this.data, (item: string) => {
  74. ListItem() {
  75. Row() {
  76. Image(item).width(50).height(50)
  77. Text(item).fontSize(20).margin({ left: 10 })
  78. }.margin({ left: 10, right: 10 })
  79. }
  80. .onClick(() => {
  81. // 每点击一次列表项,数据增加一项
  82. this.data.pushData('/path/image' + this.data.totalCount() + '.png')
  83. })
  84. }, item => item)
  85. }
  86. }
  87. }

本次作业:

列表示例:

  1. @Entry
  2. @Component
  3. struct zuoye3 {
  4. build() {
  5. Column(){
  6. List( ) {
  7. ListItem(){
  8. Text("示例1")
  9. .fontSize(30).width("100%").height("10%").backgroundColor("#DCDCDC")
  10. }
  11. ListItem(){
  12. Text("示例2")
  13. .fontSize(30).width("100%").height("10%").backgroundColor("#BABABA")
  14. }
  15. ListItem(){
  16. Text("示例3")
  17. .fontSize(30) .width("100%").height("10%").backgroundColor("#BDDB")
  18. }
  19. ListItem(){
  20. Text("示例4")
  21. .fontSize(30).width("100%").height("10%").backgroundColor("#1264")
  22. }
  23. }
  24. }
  25. .width("100%").height("100%").justifyContent(FlexAlign.Center)
  26. }
  27. }

if-else-else if示例:

  1. //import {child} from"../applicationability/child"
  2. @Entry
  3. @Component
  4. struct zuoye5{
  5. @State fathernum : number= -1
  6. build(){
  7. Column(){
  8. Column(){
  9. if(this.fathernum%2===0){
  10. Text('count is negative')
  11. .fontSize(50)
  12. .fontWeight(FontWeight.Bold)
  13. }
  14. else if(this.fathernum%3===0){
  15. Text('even')
  16. .fontSize(50)
  17. .fontWeight(FontWeight.Bold)
  18. } else{
  19. Text('odd')
  20. .fontSize(50)
  21. .fontWeight(FontWeight.Bold)
  22. }
  23. }
  24. }
  25. .width("100%").height("100%").justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center)
  26. }
  27. }

讲解:if-else组件必须在容器组件内使用。特别需要注意的一点是对于fathernum的赋值情况:其中的

number= -1不可少,因为加了number才能够确定fathernum才有类型。我做的时候犯的错误有,没加number,以及写成了:@State fathernum : number= “-1”,这里是不需要加引号的。

循环渲染示例:

  1. @Entry
  2. @Component
  3. struct zuoye4 {
  4. private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] // 一个列表
  5. build() {
  6. Column() {
  7. Column() {
  8. List({ space: 20 }) {
  9. //for循环渲染出10个Listitem小列表
  10. ForEach(this.arr, (item) => {
  11. ListItem() {
  12. //使列表里面的元素转化为字符串出现到文本里
  13. Text(item.toString())
  14. // 设置长度
  15. .width('100%')
  16. // 设置宽度
  17. .height(90)
  18. // 文字大小
  19. .fontSize(36)
  20. // 文字居中
  21. .textAlign(TextAlign.Center)
  22. // 背景颜色
  23. .backgroundColor("#007DEF")
  24. // 使ListItem出现圆角
  25. .borderRadius(30)
  26. }
  27. })
  28. }
  29. // 排列方向
  30. .listDirection(Axis.Vertical)
  31. }
  32. .width("90%")
  33. .height('90%')
  34. }
  35. .width('100%')
  36. .height('100%')
  37. .justifyContent(FlexAlign.SpaceAround)
  38. }
  39. }

这里需要注意的是:要设置排列的方向 .listDirection(Axis.Vertical)不可少

父子组件:

父组件:

  1. import{child} from"../applicationability/child"
  2. @Entry
  3. @Component
  4. struct zuoye6{
  5. //设fathernum为number类型值为0
  6. @State fathernum:number = 0
  7. //设fatherstatu为boolean类型值为true
  8. @State fatherstatu:boolean = true
  9. build() {
  10. Row() {
  11. Column() {
  12. child({ childnum: $fathernum,childnum1:$fatherstatu})
  13. }
  14. .width('100%')
  15. }
  16. .height('100%')
  17. }
  18. }

子组件:

  1. @Component
  2. export struct child{ //导出
  3. @Link childnum:number
  4. @Link childnum1:boolean
  5. build() {
  6. Column({space:10}) {
  7. //布尔类型:如果真执行,如果假则不执行;真假由childnum1的值决定
  8. if(this.childnum1){
  9. //进行字符的转换
  10. Text(this.childnum.toString())
  11. .fontSize(80)
  12. .fontColor(Color.Red)
  13. }
  14. //设置一个按钮
  15. Button('增加')
  16. .width(200).height(90)
  17. .fontSize(30)
  18. //设置点击事件
  19. .onClick(()=>{
  20. // 每点击一次,childnum+1
  21. this.childnum++
  22. })
  23. Button('减少')
  24. .width(200).height(90)
  25. .fontSize(30)
  26. .onClick(()=>{
  27. //点击后childnum的值减1
  28. this.childnum--
  29. })
  30. Button('归零')
  31. .width(200).height(90)
  32. .fontSize(30)
  33. .onClick(()=>{
  34. // 点击之后归零
  35. this.childnum = 0
  36. })
  37. Button('显示')
  38. .width(200).height(90)
  39. .fontSize(30)
  40. .onClick(()=>{
  41. //开关设置,也就是辨别真假
  42. this.childnum1 =! this.childnum1
  43. })
  44. }
  45. }
  46. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/88404
推荐阅读
相关标签
  

闽ICP备14008679号