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

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

    2_4_1

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

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

    2_4_2

鸿蒙OS开发更多内容↓点击鸿蒙NEXT星河版开发学习文档》HarmonyOS与OpenHarmony技术

LazyForEach循环渲染

搜狗高速浏览器截图20240326151547.png

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 接口的对象,需要开发者实现相关接口。
  2. IDataSource 定义如下:

    export declare interface IDataSource {
      totalCount(): number;
      getData(index: number): any;
      registerDataChangeListener(listener: DataChangeListener): void;
      unregisterDataChangeListener(listener: DataChangeListener): void;
    }
    
    • totalCount:获取数据总数。
    • getData:获取索引对应的数据。
    • registerDataChangeListener:注册改变数据的监听器。
    • unregisterDataChangeListener:注销改变数据的监听器。
  3. 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;
  }
}

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

2_4_3

打印结果如下:

[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

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


http://www.niftyadmin.cn/n/5479803.html

相关文章

javascript,DOM事件,传统事件和事件监听详解

事件三要素 事件源、事件类型、事件处理函数 传统事件 传统事件只能拿到冒泡阶段&#xff0c;不能拿到捕获阶段&#xff08;onblur、onmouseleave没有冒泡阶段&#xff09; 同一个元素的同一个事件多次注册&#xff0c;只会执行最后一次 传统事件类型 input事件作用onblu…

常见深度学习之十二大激活函数【函数定义、性质、数学公式、代码实现】

目录 前言 1、激活函数的定义与作用 2、激活函数的性质 二、常见的激活函数 2.1 Sigmoid函数&#xff1a; 1. 作用 2. 优点 3. 缺点 4. 数学公式 5.Sigmoid函数实现及可视化图像 2.2 Tanh函数 1. 函数定义 2.优点 3.缺点 4.Tanh函数实现及可视化图像 2.3ReLU 函数 &#xff1a;…

如何通过VPN访问内网?

VPN&#xff08;Virtual Private Network&#xff09;是一种通过公共网络建立私有网络连接的技术&#xff0c;可以在不同地点的网络中建立安全通道&#xff0c;实现远程访问内网资源的目的。本文将介绍如何通过VPN访问内网&#xff0c;并介绍一款名为“天联”的VPN服务。 什么是…

创建型模式--4.抽象工厂模式【弗兰奇一家】

1. 奔向大海 在海贼世界中&#xff0c;位于水之都的弗兰奇一家是由铁人弗兰奇所领导的以拆船为职业的家族&#xff0c;当然了他们的逆向工程做的也很好&#xff0c;会拆船必然会造船。船是海贼们出海所必备的海上交通工具&#xff0c;它由很多的零件组成&#xff0c;从宏观上看…

蓝桥杯算法题:外卖店优先级

“饱了么”外卖系统中维护着 N 家外卖店&#xff0c;编号 1∼N。每家外卖店都有一个优先级&#xff0c;初始时 (0时刻) 优先级都为 0。每经过 1个时间单位&#xff0c;如果外卖店没有订单&#xff0c;则优先级会减少 1&#xff0c;最低减到 0&#xff1b;而如果外卖店有订单&am…

ORA-00600: internal error code, arguments: [krbcbp_9]

解决方案 1、清理过期 2、control_file_record_keep_time 修改 恢复时间窗口 RMAN (Recovery Manager) 是 Oracle 数据库的备份和恢复工具。在 RMAN 中&#xff0c;可以使用“恢复窗口”的概念来指定数据库可以恢复到的时间点。这个时间点是基于最近的完整备份或增量备份。 …

LeetCode 289.生命游戏————2024 春招冲刺百题计划

根据 百度百科 &#xff0c; 生命游戏 &#xff0c;简称为 生命 &#xff0c;是英国数学家约翰何顿康威在 1970 年发明的细胞自动机。 给定一个包含 m n 个格子的面板&#xff0c;每一个格子都可以看成是一个细胞。每个细胞都具有一个初始状态&#xff1a; 1 即为 活细胞 &am…

安卓系统内置语音识别技术——Speech-to-Text的研究与实践

摘要 本文聚焦于安卓系统内置的Speech-to-Text技术&#xff0c;对其基本概念、工作原理、具体使用方法、性能优劣以及典型应用场景进行深入剖析&#xff0c;并结合实例代码阐述其在安卓开发中的应用。安卓系统内置的Speech-to-Text功能作为一项基础的语音识别服务&#xff0c;为…