HarmonyOS学习笔记-条件和循环渲染

175 阅读3分钟

条件渲染if...else

使用 ifelse ifelse 根据不同条件渲染不同的UI

@Entry
@Component
struct ViewA {
  @State count: number = 0;

  build() {
    Column() {
      Text(`count的值是:${this.count}`)
        .fontSize(30)
        .padding(20)

      if (this.count < 4) {
        Text(`不满意`)
          .fontColor(Color.Red)
          .fontSize(30)
          .margin({ top: '20pv', bottom: '20pv' })
      } else if (this.count > 7) {
        Text(`很满意`)
          .fontColor(Color.Green)
          .fontSize(30)
          .margin({ top: '20pv', bottom: '20pv' })
      } else {
        Text(`一般般`)
          .fontColor(Color.Yellow)
          .fontSize(30)
          .margin({ top: '20pv', bottom: '20pv' })
      }

      Row() {
        Button('count++')
          .fontSize(30)
          .onClick(() => {
            this.count++;
          })

        Button('count--')
          .fontSize(30)
          .onClick(() => {
            this.count--;
          })
      }
    }
  }
}

默认渲染效果

image.png

点击++ 按钮,大于 7 之后的效果

image.png

循环渲染ForEach

ForEach接口基于数组类型数据来进行循环渲染,需要与容器组件配合使用,且接口返回的组件应当是允许包含在ForEach父容器组件中的子组件。例如,ListItem组件要求ForEach的父容器组件必须为List组件。

语法

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

参数说明

参数名类型必填说明
arrArray数据源,为Array类型的数组。说明:- 可以设置为空数组,此时不会创建子组件。- 可以设置返回值为数组类型的函数,例如arr.slice(1, 3),但设置的函数不应改变包括数组本身在内的任何状态变量,例如不应使用Array.splice(),Array.sort()或Array.reverse()这些会改变原数组的函数。
itemGenerator(item: Object, index: number) => void组件生成函数。
- 为数组中的每个元素创建对应的组件。
- item参数:arr数组中的数据项。- index参数(可选):arr数组中的数据项索引。说明:- 组件的类型必须是ForEach的父容器所允许的。例如,ListItem组件要求ForEach的父容器组件必须为List组件。
keyGenerator(item: Object, index: number) => string键值生成函数。- 为数据源arr的每个数组项生成唯一且持久的键值。函数返回值为开发者自定义的键值生成规则。- item参数:arr数组中的数据项。- index参数(可选):arr数组中的数据项索引。说明:- 如果函数缺省,框架默认的键值生成函数为(item: T, index: number) => { return index + '__' + JSON.stringify(item); },- 键值生成函数不应改变任何组件状态。

ForEach 本身使用比较简单,主要是 key 导致的组件更新比较复杂。

key 生成规则

在ForEach循环渲染过程中,系统会为每个数组元素生成一个唯一且持久的键值,用于标识对应的组件。当这个键值变化时,ArkUI框架将视为该数组元素已被替换或修改,并会基于新的键值创建一个新的组件。

ForEach提供了一个名为keyGenerator的参数,这是一个函数,开发者可以通过它自定义键值的生成规则。如果开发者没有定义keyGenerator函数,则ArkUI框架会使用默认的键值生成函数,即(item: Object, index: number) => { return index + '__' + JSON.stringify(item); }。

ArkUI框架对于ForEach的键值生成有一套特定的判断规则,这主要与itemGenerator函数的第二个参数index以及keyGenerator函数的第二个参数index有关,

下图是官方对 key生成规则的说明

image.png

@Entry
@Component
struct Parent {
  @State list: Array<string> = ['商品1', '商品2', '商品3'];

  build() {
    Row() {
      Column() {
        ForEach(this.list, (item: string) => {
          Text(item).fontSize(40)
        }, (item: string) => item)
      }
      .width('100%')
      .height('100%')
    }
    .height('100%')
    .backgroundColor(0xF1F3F5)
  }
}

image.png

注意: key 必须是字符串

image.png

如果出现 key 相同的情况,渲染会异常

@Entry
@Component
struct Parent {
  @State list: Array<string> = ['商品1', '商品2', '商品3', '商品2'];

  build() {
    Row() {
      Column() {
        // 商品2 出现两次 导致key重复 第二个商品2不会被渲染
        ForEach(this.list, (item: string) => {
          Text(item).fontSize(40)
        }, (item: string) => item)
      }
      .width('100%')
      .height('100%')
    }
    .height('100%')
    .backgroundColor(0xF1F3F5)
  }
}

image.png

在使用的时候要注意确保 key 的唯一

在对数据对象做更新操作的时候也要特别注意