《ArkUI实战》之渲染控制语法

ArkUI开发框架是一套构建 HarmonyOS / OpenHarmony 应用界面的声明式UI开发框架,它支持程序使用 if/else 条件渲染, ForEach 循环渲染以及 LazyForEach 懒加载渲染。本节笔者介绍一下这三种渲染方式的使用。

if/else条件渲染

使用 if/else 进行条件渲染需要注意以下情况:

  • if 条件语句可以使用状态变量。
  • 使用 if 可以使子组件的渲染依赖条件语句。
  • 必须在容器组件内使用。
  • 某些容器组件限制子组件的类型或数量。将if放置在这些组件内时,这些限制将应用于 ifelse 语句内创建的组件。例如,Grid 组件的子组件仅支持 GridItem 组件,在 Grid 组件内使用条件渲染时,则 if 条件语句内仅允许使用 GridItem 组件。

简单样例如下所示:

    @Entry @Component struct ComponentTest {

      @State showImage: boolean = false;

      build() {
        Column({space: 10}) {

          if (this.showImage) {            // 显示图片
            Image($r("app.media.test"))
              .width(160)
              .height(60)
              .backgroundColor(Color.Pink)
          } else {                         // 显示文本
            Text('Loading...')
              .fontSize(23)
              .width(160)
              .height(60)
              .backgroundColor(Color.Pink)
          }

          Button(this.showImage ? 'Image Loaded' : 'Load Image')    // 按钮文字
            .size({width: 160, height: 40})
            .backgroundColor(this.showImage ? Color.Gray : '#aabbcc')// 按钮背景色
            .onClick(() => {
              this.showImage = true;                                 // 设置标记位
            })
        }
        .width('100%')
        .height('100%')
        .padding(10)
      }
    }

样例运行结果如下图所示:

ForEach循环渲染

ArkUI开发框架提供循环渲染(ForEach组件)来迭代数组,并为每个数组项创建相应的组件。

ForEach 定义如下:

interface ForEach {(
	arr: Array<any>, 
	itemGenerator: (item: any, index?: number) => void,
  keyGenerator?: (item: any, index?: number) => string
  ): ForEach;
}
  • arr:必须是数组,允许空数组,空数组场景下不会创建子组件。

  • itemGenerator:子组件生成函数,为给定数组项生成一个或多个子组件。

  • keyGenerator:匿名参数,用于给定数组项生成唯一且稳定的键值。

简单样例如下所示:

    @Entry @Component struct ComponentTest {

      private textArray: string[] = ["1", "2", "3", "4", "5"];        // 数据源

      build() {
        Column({space: 10}) {
          ForEach(this.textArray, (item: string, index?: number) => { // 循环数组创建每一个Item
            Text(`Text: ${item}`)                                     // 可以生成一个或多个子组件
              .fontSize(20)
              .backgroundColor(Color.Pink)
              .margin({ top: 10 })
          })
        }
        .width('100%')
        .height('100%')
        .padding(10)
      }
    }

样例运行结果如下图所示:

LazyForEach循环渲染

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

  1. LazyForEach 定义如下:
    // LazyForEach定义
    interface LazyForEach {(
    	dataSource: IDataSource, 
      itemGenerator: (item: any, index?: number) => void,
      keyGenerator?: (item: any, index?: number) => string
      ): LazyForEach;
    }

    // IDataSource定义
    export declare interface IDataSource {
      totalCount(): number;
      getData(index: number): any;
      registerDataChangeListener(listener: DataChangeListener): void;
      unregisterDataChangeListener(listener: DataChangeListener): void;
    }

    // DataChangeListener定义
    export declare interface DataChangeListener {
      onDataReloaded(): void;
      onDataAdded(index: number): void;
      onDataMoved(from: number, to: number): void;
      onDataDeleted(index:number): void;
      onDataChanged(index:number): void;
    }
  • itemGenerator:子组件生成函数,为给定数组项生成一个或多个子组件。
  • keyGenerator:匿名参数,用于给定数组项生成唯一且稳定的键值。
  • dataSource:实现 IDataSource 接口的对象,需要开发者实现相关接口。
  1. IDataSource 定义如下:
    export declare interface IDataSource {
      totalCount(): number;
      getData(index: number): any;
      registerDataChangeListener(listener: DataChangeListener): void;
      unregisterDataChangeListener(listener: DataChangeListener): void;
    }
  • totalCount:获取数据总数。
  • getData:获取索引对应的数据。
  • registerDataChangeListener:注册改变数据的监听器。
  • unregisterDataChangeListener:注销改变数据的监听器。
  1. DataChangeListener 定义如下:
    export declare interface DataChangeListener {
      onDataReloaded(): void;
      onDataAdded(index: number): void;
      onDataMoved(from: number, to: number): void;
      onDataDeleted(index:number): void;
      onDataChanged(index:number): void;
    }
  • onDataReloaded:item重新加载数据时的回调。
  • onDataAdded:item新添加数据时的回调。
  • onDataMoved:item数据移动时的回调。
  • onDataDeleted:item数据删除时的回调。
  • onDataChanged:item数据变化时的回调。

简单样例如下:

// 定义Student
class Student {
  public sid: number;
  public name: string;
  public age: number
  public address: string
  public avatar: string
  constructor(sid: number = -1, name: string, age: number = 16, address: string = '北京', avatar: string = "") {
    this.sid = sid;
    this.name = name;
    this.age = age;
    this.address = address;
    this.avatar = avatar;
  }
}

// 定义DataSource
abstract class BaseDataSource<T> implements IDataSource {

  private mDataSource: T[] = new Array();

  constructor(dataList: T[]) {
    this.mDataSource = dataList;
  }

  totalCount(): number {
    return this.mDataSource == null ? 0 : this.mDataSource.length
  }

  getData(index: number): T|null {
    return index >= 0 && index < this.totalCount() ? this.mDataSource[index] : null;
  }

  registerDataChangeListener(listener: DataChangeListener) {
  }

  unregisterDataChangeListener(listener: DataChangeListener) {
  }

}

// 
class StudentDataSource extends BaseDataSource<Student> {
  constructor(students: Student[]) {
    super(students)
  }
}

function mock(): Student[] {
  var students = [];
  for(var i = 0; i < 20; i++) {
    students[i] = new Student(i, "student:" + i, i + 10, "address:" + i, "app.media.test")
  }
  return students;
}

@Entry @Component struct ComponentTest {

  // mock数据
  private student: Student[] = mock();

  // 创建dataSource
  private dataSource: StudentDataSource = new StudentDataSource(this.student);

  build() {
    Column({space: 10}) {
      List() {
        LazyForEach(this.dataSource, (item: Student) => {// LazyForEach使用自定义dataSource
          ListItem() {
            Row() {
              Image($r("app.media.test"))
                .height('100%')
                .width(80)
              Column() {
                Text(this.getName(item)) // 调用getName验证懒加载
                  .fontSize(20)
                Text('address: ' + item.address)
                  .fontSize(17)
              }
              .margin({left: 5})
              .alignItems(HorizontalAlign.Start)
              .layoutWeight(1)
            }
            .width('100%')
            .height('100%')
          }
          .width('100%')
          .height(60)
        })
      }
      .divider({
        strokeWidth: 3,
        color: Color.Gray
      })
      .width('90%')
      .height(160)
      .backgroundColor(Color.Pink)
    }
    .width('100%')
    .height('100%')
    .padding(10)
  }

  getName(item: Student): string {
    console.log("index: " + item.sid); // 打印item下标日志
    return 'index:' + item.sid + ", " + item.name;
  }
}

打印结果如下:

[phone][Console    INFO]  04/02 23:54:19 82919424 app Log: Application onCreate
[phone][Console   DEBUG]  04/02 23:54:19 82919424 app Log: index: 0
[phone][Console   DEBUG]  04/02 23:54:19 82919424 app Log: index: 1
[phone][Console   DEBUG]  04/02 23:54:19 82919424 app Log: index: 2
[phone][Console   DEBUG]  04/02 23:54:19 82919424 app Log: index: 3
[phone][Console   DEBUG]  04/02 23:54:19 82919424 app Log: index: 4
[phone][Console   DEBUG]  04/02 23:54:19 82919424 app Log: index: 5

📢:使用懒加载,可以有效的降低资源占用

小结

本节主要讲解了ArkUI开发框架的渲染控制语法,读者熟练掌握后可以随心所欲的控制页面的显示逻辑了(#.#)

为了能让大家更好的学习鸿蒙(HarmonyOS NEXT)开发技术,这边特意整理了《鸿蒙开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05

《鸿蒙开发学习手册》:

如何快速入门:https://qr21.cn/FV7h05

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. ……

开发基础知识:https://qr21.cn/FV7h05

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. ……

基于ArkTS 开发:https://qr21.cn/FV7h05

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. ……

鸿蒙开发面试真题(含参考答案):https://qr18.cn/F781PH

鸿蒙开发面试大盘集篇(共计319页):https://qr18.cn/F781PH

1.项目开发必备面试题
2.性能优化方向
3.架构方向
4.鸿蒙开发系统底层方向
5.鸿蒙音视频开发方向
6.鸿蒙车载开发方向
7.鸿蒙南向开发方向

  • 25
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值