鸿蒙开发-ArkTS 语言-循环渲染

news2024/11/16 15:37:38

鸿蒙开发-ArkTS 语言-状态管理

4. 渲染控制

对于 UI 渲染,可以基于数据结构选择一些内置方法(例如:ForEach)快速渲染 UI 结构。

4.1 if-else条件渲染

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

条件渲染语句允许基于条件在组件内构建不同子组件,支持if、else、else if语句,条件可以使用状态变量,但需遵循父子组件关系规则,确保每个分支内创建至少一个组件,且子组件类型和数量需符合父组件限制。

代码示例:

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

  build() {
    Column() {
      Text(`count=${this.count}`)

      if (this.count >= 0) {
        Text(`count 为正数`)
          .fontColor(Color.Green)
      } else {
        Text(`count 为负数`)
          .fontColor(Color.Red)
      }

      Button('增 count')
        .onClick(() => {
          this.count++;
        })

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

图示:

gif11

4.2 ForEach:循环渲染

必须使用数组(允许空数组),设置的循环函数不允许改变源数组。

一共三个参数:

  1. ForEach组件接受arr属性作为数组输入,必须是数组类型,允许为空数组,可用返回数组的函数。数组为空时,不会创建子组件。

  2. itemGenerator是必需的,是一个lambda函数,根据数组中的每个数据项生成一个或多个子组件。

  3. 可选的keyGenerator是一个匿名函数,用于生成数组中每个数据项的唯一 key 值。

简单的示例:

@Entry
@Component
struct MyComponent {
  @State arr: number[] = [10, 20, 30];

  build() {
    Column({ space: 5 }) {
      Button('翻转数组')
        .onClick(() => {
          this.arr.reverse();
        })
      ForEach(this.arr, (item: number) => {
        Text(`此项值: ${item}`).fontSize(18)
        Divider().strokeWidth(2)
      }, (item: number) => item.toString())
    }
  }
}

效果如下:

gif12

配合 @ObjectLInk 的 ForEach 示例

let NextID: number = 0;

@Observed
class MyCounter {
  public id: number;
  public c: number;

  constructor(c: number) {
    this.id = NextID++;
    this.c = c;
  }
}

@Component
struct CounterView {
  @ObjectLink counter: MyCounter;
  label: string = '计数器视图';

  build() {
    Button(`计数器视图 [${this.label}] this.counter.c=${this.counter.c} +1`)
      .width(400).height(50)
      .onClick(() => {
        this.counter.c += 1;
      })
  }
}

@Entry
@Component
struct MainView {
  @State firstIndex: number = 0;
  @State counters: Array<MyCounter> = [new MyCounter(0), new MyCounter(0), new MyCounter(0),
    new MyCounter(0), new MyCounter(0)];

  build() {
    Column() {
      ForEach(this.counters.slice(this.firstIndex, this.firstIndex + 3),
        (item) => {
          CounterView({ label: `计数器项目 #${item.id}`, counter: item })
        },
        (item) => item.id.toString()
      )
      Button(`计数器:向上移动`)
        .width(200).height(50)
        .onClick(() => {
          this.firstIndex = Math.min(this.firstIndex + 1, this.counters.length - 3);
        })
      Button(`计数器:向下移动`)
        .width(200).height(50)
        .onClick(() => {
          this.firstIndex = Math.max(0, this.firstIndex - 1);
        })
    }
  }
}

图示:

gif13

4.3 LazyForEach:数据懒加载

LazyForEach是一个用于按需迭代数据并创建组件的接口,适用于滚动容器以提高性能。它接受数据源、子组件生成函数和可选的键值生成函数作为参数。在每次迭代中,子组件生成函数生成一个子组件,并且键值生成函数可选地用于为数据项生成唯一的键值。

同时,数据变化监听器(DataChangeListener)提供了各种通知方法,如重新加载数据、数据添加、数据移动、数据删除和数据变化。在使用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; // 改变数据时调用
}

懒加载示例:

// 实现基本的IDataSource以处理数据监听器
class BasicDataSource implements IDataSource {
  private listeners: DataChangeListener[] = [];

  // 获取数据总数
  public totalCount(): number {
    return 0;
  }

  // 获取特定索引的数据
  public getData(index: number): any {
    return undefined;
  }

  // 注册数据变化监听器
  registerDataChangeListener(listener: DataChangeListener): void {
    if (this.listeners.indexOf(listener) < 0) {
      console.info('添加监听器');
      this.listeners.push(listener);
    }
  }

  // 注销数据变化监听器
  unregisterDataChangeListener(listener: DataChangeListener): void {
    const pos = this.listeners.indexOf(listener);
    if (pos >= 0) {
      console.info('移除监听器');
      this.listeners.splice(pos, 1);
    }
  }

  // 通知数据重新加载
  notifyDataReload(): void {
    this.listeners.forEach(listener => {
      listener.onDataReloaded();
    });
  }

  // 通知数据添加
  notifyDataAdd(index: number): void {
    this.listeners.forEach(listener => {
      listener.onDataAdd(index);
    });
  }

  // 通知数据变化
  notifyDataChange(index: number): void {
    this.listeners.forEach(listener => {
      listener.onDataChange(index);
    });
  }

  // 通知数据删除
  notifyDataDelete(index: number): void {
    this.listeners.forEach(listener => {
      listener.onDataDelete(index);
    });
  }

  // 通知数据移动
  notifyDataMove(from: number, to: number): void {
    this.listeners.forEach(listener => {
      listener.onDataMove(from, to);
    });
  }
}

class MyDataSource extends BasicDataSource {
  private dataArray: string[] = [];

  // 获取数据总数
  public totalCount(): number {
    return this.dataArray.length;
  }

  // 获取特定索引的数据
  public getData(index: number): any {
    return this.dataArray[index];
  }

  // 添加数据
  public addData(index: number, data: string): void {
    this.dataArray.splice(index, 0, data);
    this.notifyDataAdd(index);
  }

  // 推送数据
  public pushData(data: string): void {
    this.dataArray.push(data);
    this.notifyDataAdd(this.dataArray.length - 1);
  }
}

@Entry
@Component
struct MyComponent {
  aboutToAppear() {
    for (var i = 100; i >= 80; i--) {
      this.data.pushData(`Hello ${i}`);
    }
  }

  private data: MyDataSource = new MyDataSource();

  build() {
    List({ space: 3 }) {
      // 使用LazyForEach按需迭代数据
      LazyForEach(this.data, (item: string) => {
        ListItem() {
          Row() {
            Text(item).fontSize(50)
              .onAppear(() => {
                console.info("出现:" + item);
              });
          }.margin({ left: 10, right: 10 });
        }
        .onClick(() => {
          this.data.pushData(`Hello ${this.data.totalCount()}`);
        });
      }, item => item);
    }.cachedCount(5); // 设置缓存的数据数量
  }
}

图示:

gif14

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1250726.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ORA-14452: 试图创建, 变更或删除正在使用的临时表中的索引

在编写一个test存储过程中出现一个错误报告:ORA-14452: 试图创建, 变更或删除正在使用的临时表中的索引,代码如下 create or replace PROCEDURE TMP_TRANSCRIPT AS str_sql varchar2(500);v_flag number:0; --标识 begin--判断临时表是否存在SELECT COUNT(*) into v_flag FROM…

【版本管理 | Git 】Git最佳实践系列(一) —— LFS .gitignore 最佳实践,确定不来看看?

&#x1f935;‍♂️ 个人主页: AI_magician &#x1f4e1;主页地址&#xff1a; 作者简介&#xff1a;CSDN内容合伙人&#xff0c;全栈领域优质创作者。 &#x1f468;‍&#x1f4bb;景愿&#xff1a;旨在于能和更多的热爱计算机的伙伴一起成长&#xff01;&#xff01;&…

华大基因基因检测产品发布,助力早发冠心病风险评估

冠状动脉性心脏病&#xff0c;简称冠心病。冠心病作为导致猝死的常见原因之一&#xff0c;近年来备受关注。早发冠心病是指冠心病发病年龄男性≤55岁&#xff0c;女性≤60岁。早发冠心病是一种发病时心肌损伤严重的冠心病&#xff0c;由于心肌缺血&#xff0c;还有可能会导致急…

基于C#实现双端队列

话说有很多数据结构都在玩组合拳&#xff0c;比如说&#xff1a;块状链表&#xff0c;块状数组&#xff0c;当然还有本篇的双端队列&#xff0c;是的&#xff0c;它就是栈和队列的组合体。 一、概念 我们知道普通队列是限制级的一端进&#xff0c;另一端出的 FIFO 形式&#…

类和对象(4)——补充内容+DateOJ题

Date类型的OJ 一&#xff0c;static成员例题 二&#xff0c;DateOJ题一&#xff0c;[计算日期到天数转换](https://www.nowcoder.com/practice/769d45d455fe40b385ba32f97e7bcded?tpId37&&tqId21296&rp1&ru/activity/oj&qru/ta/huawei/question-ranking)1…

Python 自动化用处太大了!|python自动整理文件,一键完成!

随着时代的发展及人工智能的到来&#xff0c;Python 自动化办公能力几乎已成为每个岗位的必备技能&#xff01; 而且到处可见的抖音、朋友圈铺天盖地宣传 Python 可以轻松达到办公自动化&#xff0c;并且学习没门槛&#xff0c;是真的吗&#xff1f; 我很负责的告诉大家&#…

数字化转型如何赋能企业实现数字化增值?

随着科技的不断发展&#xff0c;数字化转型已经成为了企业营销的重要趋势。数字化转型不仅可以提高企业的运营效率&#xff0c;还可以更好地满足消费者的需求&#xff0c;提升企业的市场竞争力。 一、数字化转型可以提高企业营销的精准性 在传统的企业营销中&#xff0c;营销人…

透过对话聊天聊网络tcp三次握手四次挥手

序 说起来网络&#xff0c;就让我想起的就是一张图。我在网上可以为所欲为&#xff0c;反正你又不能顺着网线来打我。接下来我们来详细说一下网络到底是怎么连接的。 TCP三次打招呼 首先我会用男女生之间的聊天方式&#xff0c;来举一个例子。 从tcp三次握手来说&#xff0c;…

GIT版本控制和常用命令使用介绍

GIT版本控制和常用命令使用介绍 1. 版本控制1.1 历史背景1.2 什么是版本控制1.3 常见版本控制工具1.4 版本控制的分类 2 Git介绍2.1 Git 工作流程2.2 基本概念2.3 文件的四种状态2.4 忽略文件2.5 Git命令2.5.1 查看本地git配置命令2.5.2 远程库信息查看命令2.5.3 分支交互命令2…

【网络】传输层 --- 详解TCP协议

目录 一、协议段格式及其策略确认应答(ACK)机制6个标志位超时重传流量控制滑动窗口1、先谈滑动窗口一般情况2、再谈特殊窗口 拥塞控制拥塞窗口 延迟应答&&捎带应答面向字节流粘包问题 二、三次握手和四次挥手三次握手为什么是3次&#xff1f;不是2、4、5、6次呢 四次挥…

鸿蒙开发-ArkTS 语言-状态管理

鸿蒙开发-ArkTS 语言-基础语法 3. 状态管理 变量必须被装饰器装饰才能成为状态变量&#xff0c;状态变量的改变才能导致 UI 界面重新渲染 概念描述状态变量被状态装饰器装饰的变量&#xff0c;改变会引起UI的渲染更新。常规变量没有状态的变量&#xff0c;通常应用于辅助计算…

1. git入门操作

1. git入门操作 1、基本名词解释 图片 名词含义index索引区&#xff0c;暂存区master分支名&#xff0c;每个仓库都有个master&#xff0c;它作为主分支。branch其他分支&#xff0c;我们可以把master分支上的代码拷贝一份&#xff0c;重新命名为其他分支名work space就是我…

竞赛python区块链实现 - proof of work工作量证明共识算法

文章目录 0 前言1 区块链基础1.1 比特币内部结构1.2 实现的区块链数据结构1.3 注意点1.4 区块链的核心-工作量证明算法1.4.1 拜占庭将军问题1.4.2 解决办法1.4.3 代码实现 2 快速实现一个区块链2.1 什么是区块链2.2 一个完整的快包含什么2.3 什么是挖矿2.4 工作量证明算法&…

PyTorch-ReID重识别算法库与数据集资料汇总

Torchreid 是一个用于深度学习人员重新识别的库&#xff0c;用 PyTorch 编写&#xff0c;为我们的 ICCV’19 项目 Omni-Scale Feature Learning for Person Re-Identification 开发。 PyTorch-ReID的特点是 多GPU训练支持图像和视频 REID端到端培训和评估极其轻松地准备 Rei…

如何找出excel中两列数据中不同的值(IF函数的用法)

第一部分&#xff0c;举例&#xff1a; 例1&#xff1a; 如下图所示&#xff0c;A列和B列是需要比较的数据&#xff0c;C列为对比规则&#xff1a;IF(A2B2,"是","否") 示例图 例2&#xff1a;给B列的成绩评等级 C列的规则&#xff1a; IF(B2>85,&qu…

RPC和HTTP的区别

目录 1、RPC是什么 1.1 概念 1.2 RPC的组成部分 1.3 常见的 RPC 技术和框架 1.4 RPC的工作流程 2、HTTP是什么 2.1 概念 2.2 HTTP的消息格式 2.3 HTTP响应状态码有哪些 3、⭐RPC和HTTP的区别 小结 1、RPC是什么 1.1 概念 RPC&#xff08;Remote Procedure Call&am…

全国甲骨文识读大会用到哪些竞赛软件

2023年&#xff0c;全国甲骨文识读大会第1季在“中华字都安阳”举办&#xff0c;天纵竞赛软件为此次高端知识竞赛提供软件支持。 甲骨文识读大会分为海选、初赛、复赛、决赛4个阶段&#xff0c;不分年龄、性别、职业、地域&#xff0c;并邀请国内甲骨文和殷商文化方面专家学者组…

Unity-类-Vector

Vector矢量 是一个基本的数学概念,它允许你描述方向和大小。在游戏和应用中,矢量通常用于描述一些基本属性,如角色的位置、物体移动的速度或两个物体之间的距离。 矢量算术是计算机编程很多方面(如图形、物理和动画)的基础,深入了解这一主题对于充分发挥 Unity 的功能很有…

python实现炫酷的屏幕保护程序!

今天写了桌面保护程序。先来看看效果吧。 完全可以作为屏保程序了&#xff0c;老方式&#xff1a;以下是实现的代码&#xff1a; from tkinter import *from time import strftime​def update_time():global i, j current_time strftime(%H:%M:%S)time_label.config(textcu…

软件工程简明教程

软件工程简明教程 何为软件工程&#xff1f; 1968 年 NATO&#xff08;北大西洋公约组织&#xff09;提出了软件危机&#xff08;Software crisis&#xff09;一词。同年&#xff0c;为了解决软件危机问题&#xff0c;“软件工程”的概念诞生了。一门叫做软件工程的学科也就应…