HarmonyOS4.0 系列——06、渲染之条件渲染、循环渲染以及懒加载渲染

时间:2024-01-22 12:55:16

HarmonyOS4.0 系列——06、渲染之条件渲染、循环渲染以及懒加载渲染

if/else:条件渲染

ArkTS 提供了渲染控制的能力。条件渲染可根据应用的不同状态,使用 if、else 和 else if 渲染对应状态下的 UI 内容。

写法和 TS 的一样,简单看一下即可

@Entry
@Component
struct IfForEach {
  @State status: boolean = true

  build() {
    Row() {
      Column() {
        Button('按钮')
          .fontSize(30)
          .width(150)
          .height(50)
          .onClick(() => {
            this.status = !this.status;
          })
        if (this.status) {
          if_son({ content: 'Southern Wind' })
        } else {
          if_son({ content: '隐藏' })
        }

      }
      .width('100%')
    }
    .height('100%')
  }
}

@Component
struct if_son {
  content: string
  build() {
    Text(this.content)
      .fontSize(30)
  }
}

效果:

HarmonyOS4.0 系列——06、渲染之条件渲染、循环渲染以及懒加载渲染_数据

另外,@State 定义的变量归父组件所有。因此,当子组件实例被删除时,该变量不会被销毁。子组件通过@Link装饰器引用状态。状态必须从子级移动到其父级(或父级的父级),以避免在条件内容或重复内容被销毁时丢失状态。

条件语句的嵌套对父组件的相关规则也没有影响。

例:

@Entry
@Component
struct CompA {
  @State toggle: boolean = false;
  @State toggleColor: boolean = false;

  build() {
    Column() {
      Divider().margin(20)
      if (this.toggle) {
        Text('第一个状态为true').margin(10)
          .backgroundColor('#aaffaa').fontSize(20)
        // 内部if语句
        if (this.toggleColor) {
          Text('两个状态都为true').margin(10)
            .backgroundColor('#00aaaa').fontSize(15)
        } else {
          Text('第一个状态为true第二个状态为false').margin(10)
            .backgroundColor('#aaaaff').fontSize(15)
        }
      } else {
        Text('第一个状态为false').fontSize(20).margin(10)
          .backgroundColor('#ffaaaa')
        if (this.toggleColor) {
          Text('第一个状态为false,第二个状态为true').margin(10)
            .backgroundColor('#00aaaa').fontSize(15)
        } else {
          Text('两个状态都为false').margin(10)
            .backgroundColor('#aaaaff').fontSize(15)
        }
      }
      Divider().margin(20)

      Button('第一个状态').margin(10)
        .onClick(() => {
          this.toggle = !this.toggle;
        })
      Button('第二个状态')
        .onClick(() => {
          this.toggleColor = !this.toggleColor;
        })
    }
    .width('100%')
  }
}

因为他默认两个状态都为 false 触发第一个状态为false'两个状态都为false文本, 一共是四种效果:

  • true true
  • ture false
  • false false
  • false true

效果:

HarmonyOS4.0 系列——06、渲染之条件渲染、循环渲染以及懒加载渲染_键值_02

ForEach

接口描述:

ForEach(
  arr: any[],
  itemGenerator: (item: any, index?: number) => void,
  keyGenerator?: (item: any, index?: number) => string
)

第一个参数为数组,允许设置为空数组,空数组场景下将不会创建子组件。 第二个参数其实就是生成遍历出来的元素和索引值,和 js 中 forEach 用法一致,只是写法略微改动。 第三个参数为匿名函数。用于给数组中的每一个数据项生成唯一且固定的键值。键值生成器的功能是可选的,但是,为了使开发框架能够更好地识别数组更改,提高性能,建议提供。如将数组反向时,如果没有提供键值生成器,则 ForEach 中的所有节点都将重建。其实也就是 vue 中 for 循环的唯一键值 key,等同于:key="item.id"或者:key="index"

  • ForEach 必须在容器组件内使用。

使用场景

@Entry
@Component
struct ForEachPage {
  @State message: string = 'Hello World'
  @State flag: boolean |string = false
  @State arr: Array<object> = [
    {
      id: 1,
      name: 'ArkTS',
    },
    {
      id: 2,
      name: 'HTML'
    },
    {
      id: 3,
      name: 'CSS',
    },
    {
      id: 4,
      name: 'Javascript'
    },
    {
      id: 5,
      name: 'PHP'
    }
    ,
    {
      id: 6,
      name: 'WebGL'
    },
    {
      id: 7,
      name: 'Node'
    },
    {
      id: 8,
      name: 'Go'
    }, {
    id: 9,
    name: 'Vue'
  },
    {
      id: 10,
      name: 'react'
    }, {
    id: 11,
    name: 'IOS'
  }, {
    id: 12,
    name: 'Southern Wind'
  },

  ]

  build() {
    Row() {
      Column() {
        Text(this.message).fontSize(50)
        Button('取反').onClick(()=>{
          this.flag=!this.flag;
          console.log(`${this.flag}`)
        })
        Divider().margin(10)
        List({ space: 30 }) {
          if (this.flag){
            ForEach(this.arr, (item, key) => {
              ListItem() {
                Text(`name:${item.name} --id:${item.id} -- key:${key}`)
                  .fontSize(30)
                  .textAlign(TextAlign.Center)
                  .width('100%')
                  .lineHeight(45)
                  .backgroundColor('#bbb')
              }
            }, item => item)
          }
        }.width('100%').height('80%')

      }.padding(20)
      .width('100%')
    }

  }
}

效果:

HarmonyOS4.0 系列——06、渲染之条件渲染、循环渲染以及懒加载渲染_数组_03

如果渲染长列表的话需要使用List组件,不然数组数据多的情况下滚动会出现问题

LazyForEach:数据懒加载

LazyForEach 就是滚动到视口的位置是才会加载,比如加载长列表图片,刚开始只渲染视口的数据,当往下拖动时才继续加载列表数据。

接口描述

LazyForEach(
    dataSource: IDataSource,             // 需要进行数据迭代的数据源
    itemGenerator: (item: any) => void,  // 子组件生成函数
    keyGenerator?: (item: any) => string // (可选) .键值生成函数
): void

官方的表格大家可以看一下具体参数名和描述

参数名

参数类型

必填

参数描述

dataSource

IDataSource

LazyForEach数据源,需要开发者实现相关接口。

itemGenerator

(item: any) =&gt; void

子组件生成函数,为数组中的每一个数据项创建一个子组件。








说明


itemGenerator的函数体必须使用大括号{...}。itemGenerator每次迭代只能并且必须生成一个子组件。itemGenerator中可以使用if语句,但是必须保证if语句每个分支都会创建一个相同类型的子组件。itemGenerator中不允许使用ForEach和LazyForEach语句。





keyGenerator

(item: any) =&gt; string

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








说明


数据源中的每一个数据项生成的键值不能重复。





关于第一个参数IDataSource也有详细的说明

interface IDataSource {
    totalCount(): number; // 获得数据总数
    getData(index: number): any; // 获取索引值对应的数据
    registerDataChangeListener(listener: DataChangeListener): void; // 注册数据改变的监听器
    unregisterDataChangeListener(listener: DataChangeListener): void; // 注销数据改变的监听器
}

关于事件DataChangeListener

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; // 改变数据时调用
}

使用限制

  • LazyForEach必须在容器组件内使用,仅有List、Grid以及Swiper组件支持数据懒加载(可配置cachedCount属性,即只加载可视部分以及其前后少量数据用于缓冲),其他组件仍然是一次性加载所有的数据
  • LazyForEach在每次迭代中,必须创建且只允许创建一个子组件。 -允许LazyForEach包含在if/else条件渲染语句中,也允许LazyForEach中出现if/else条件渲染语句。

具体代码可以参考HarmonyOS——LazyForEach