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

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

if/else:条件渲染

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

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

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)
  }
}

效果:

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

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

例:

ts 复制代码
@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

效果:

ForEach

接口描述:

ts 复制代码
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 必须在容器组件内使用。

使用场景

ts 复制代码
@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%')
    }

  }
}

效果:

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

LazyForEach:数据懒加载

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

接口描述

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

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

参数名 参数类型 必填 参数描述
dataSource IDataSource LazyForEach数据源,需要开发者实现相关接口。
itemGenerator (item: any) => void 子组件生成函数,为数组中的每一个数据项创建一个子组件。 说明 itemGenerator的函数体必须使用大括号{...}。itemGenerator每次迭代只能并且必须生成一个子组件。itemGenerator中可以使用if语句,但是必须保证if语句每个分支都会创建一个相同类型的子组件。itemGenerator中不允许使用ForEach和LazyForEach语句。
keyGenerator (item: any) => string 键值生成函数,用于给数据源中的每一个数据项生成唯一且固定的键值。当数据项在数组中的位置更改时,其键值不得更改,当数组中的数据项被新项替换时,被替换项的键值和新项的键值必须不同。键值生成器的功能是可选的,但是,为了使开发框架能够更好地识别数组更改,提高性能,建议提供。如将数组反向时,如果没有提供键值生成器,则LazyForEach中的所有节点都将重建。 说明 数据源中的每一个数据项生成的键值不能重复。

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

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

关于事件DataChangeListener

ts 复制代码
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

相关推荐
Ticnix26 分钟前
ECharts初始化、销毁、resize 适配组件封装(含完整封装代码)
前端·echarts
纯爱掌门人29 分钟前
终焉轮回里,藏着 AI 与人类的答案
前端·人工智能·aigc
twl33 分钟前
OpenClaw 深度技术解析
前端
崔庆才丨静觅36 分钟前
比官方便宜一半以上!Grok API 申请及使用
前端
星光不问赶路人1 小时前
vue3使用jsx语法详解
前端·vue.js
天蓝色的鱼鱼1 小时前
shadcn/ui,给你一个真正可控的UI组件库
前端
布列瑟农的星空1 小时前
前端都能看懂的Rust入门教程(三)——控制流语句
前端·后端·rust
Mr Xu_1 小时前
Vue 3 中计算属性的最佳实践:提升可读性、可维护性与性能
前端·javascript
jerrywus1 小时前
我写了个 Claude Code Skill,再也不用手动切图传 COS 了
前端·agent·claude
一只大侠的侠1 小时前
React Native开源鸿蒙跨平台训练营 Day16自定义 useForm 高性能验证
flutter·开源·harmonyos