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

鸿蒙开发-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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

第十三章 深度解读预训练与微调迁移,模型冻结与解冻(工具)

一个完整的代码 pythonCopy codeimport torch import torchvision import torchvision.transforms as transforms import torch.nn as nn import torch.optim as optim # 设置设备&#xff08;CPU或GPU&#xff09; device torch.device("cuda" if torch.cuda.is_a…

网络运维与网络安全 学习笔记2023.11.26

网络运维与网络安全 学习笔记 第二十七天 今日目标 NAT场景与原理、静态NAT、动态NAT PAT原理与配置、动态PAT之EasyIP、静态PAT之NAT Server NAT场景与原理 项目背景 为节省IP地址和费用&#xff0c;企业内网使用的都是“私有IP地址” Internet网络的组成设备&#xff0c…

终端移动性管理

联系前面所学的知识我们知道&#xff0c;移动性管理主要分为两大类&#xff1a;空闲状态下的移动性管理、连接状态下的移动性管理。我们今天来详细了解他们的工作原理~ 目录 移动性管理分类 1、空闲状态下的移动性管理 2、连接状态下的移动性管理 手机选择天线的原则 4G天…

vue项目npm install报错Failed at the fibersa4.0.3 install script

报错如下 解决&#xff1a;降低node版本 降到12.16.0 参考链接

SSM图书捐赠网站系统开发mysql数据库web结构java编程计算机网页源码eclipse项目

一、源码特点 SSM 图书捐赠网站系统是一套完善的信息系统&#xff0c;结合springMVC框架完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用SSM框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统具有完整的源代码和数据库 &#xff0c;系统主要采用B/…

BigDecimal的使用全面总结

BigDecimal BigDecimal可以表示任意大小&#xff0c;任意精度的有符号十进制数。所以不用怕精度问题&#xff0c;也不用怕大小问题&#xff0c;放心使用就行了。就是要注意的是&#xff0c;使用的时候有一些注意点。还有就是要注意避免创建的时候存在精度问题&#xff0c;尤其…

LeetCode Hot100 124.二叉树中的最大路径和

题目&#xff1a; 二叉树中的 路径 被定义为一条节点序列&#xff0c;序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点&#xff0c;且不一定经过根节点。 路径和 是路径中各节点值的总和。 给你一个二叉树的根节点…

一起学docker系列之十docker安装tomcat实践

目录 前言1 安装tomcat的步骤步骤 1: 查找并拉取 Tomcat 镜像步骤 2: 运行 Tomcat 容器步骤 3: 管理 Tomcat 容器步骤 4: 访问 Tomcat 首页 2 解决访问首页的404访问不到的问题2.1 Tomcat 10 的默认设置问题2.2 端口映射或防火墙问题 3 推荐使用 Tomcat 8.5 版本总结 前言 当安…

玉渊谭天对电影色彩分析的“蚊香图”复现-python

视频教程链接&#xff1a;https://www.bilibili.com/video/BV1Lu4y1t7FG/ 最终的实现效果如下&#xff1a; 前几天刷抖音刷到了玉渊谭天对于电影抽取画面制作“蚊香图”&#xff0c;相关视频片段如下。 这种制作”蚊香图“的特效当时有点触动到到我&#xff0c;根据色彩来分…

【服务器能干什么】搭建一个短网址平台,可以查看数据详情!

昨天在 YouTube 上看到又一个搭建自己短网址的视频教程&#xff0c;用的是开源的 polr&#xff0c;但是按照步骤一步步搭建下来&#xff0c;最后一步都会出现 顺哥轻创 PLAINTEXT Whoops, looks like something went wrong百度、谷歌查了一圈也没找到有效的解决方法。&#x…

qt pdf 模块简介

文章目录 1. 技术平台2. Qt pdf 模块3. cmake 使用模块4. 许可证5. 简单示例5.1 CMakeLists.txt5.2 main.cpp 6. 总结 1. 技术平台 项目说明OSwin10 x64Qt6.6compilermsvc2022构建工具cmake 2. Qt pdf 模块 Qt PDF模块包含用于呈现PDF文档的类和函数。 QPdfDocument 类加载P…

浏览器中实现可视化的方式有哪几种?带你盘点一下

前言 &#x1f4eb; 大家好&#xff0c;我是南木元元&#xff0c;热衷分享有趣实用的文章&#xff0c;希望大家多多支持&#xff0c;一起进步&#xff01; &#x1f345; 个人主页&#xff1a;南木元元 目录 可视化的含义 浏览器中实现可视化的4种方式 1. HTMLCSS 2. SVG …

Java小游戏 王者荣耀

GameFrame类 所需图片&#xff1a; package 王者荣耀;import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.io.File; import java.util.ArrayLis…

霍夫丁不等式(Hoeffding‘s inequality)

参考资料&#xff1a;Hoeffdings inequality | encyclopedia article by TheFreeDictionary 霍夫丁不等式&#xff08;Hoeffdings inequality&#xff09;描述了随机变量的和、与和的期望之差的上限&#xff1b;或者表述为&#xff1a;随机变量的均值、与均值的期望之差的上限。…

Node.js与npm的准备与操作

1.下载 Node.js官网&#xff1a;Node.jsNode.js is a JavaScript runtime built on Chromes V8 JavaScript engine.https://nodejs.org/en 打开后的界面如下&#xff1a; LTS&#xff08;Long Term Support&#xff09;&#xff1a;长期支持版&#xff0c;稳定版 Current&am…

IDEA出现cannot download sources解决方案

IDEA出现cannot download sources解决方案 问题描述 当我想看第三方库的源码的注释时需要下载源码。 点击Dodnload Sources后可能会出现cannot download sources的问题。 解决方案 这时我们只需在根目录下打开Terminal后执行下面一行代码 mvn dependency:resolve -Dclassi…

【element优化经验】el-dialog修改title样式

目录 前言 解决之路 1.把默认的这个图标隐藏&#xff0c;官方的api有这个属性&#xff1a;showClose值设置false. 2.title插槽定制&#xff1a;左边定制标题&#xff0c;右边定制按钮区域。 3.背景颜色修改&#xff1a;默认title是有padding的需要把它重写调&#xff0c;然…

QQ录屏保存到哪了?教你快速找到保存位置

qq录屏是许多用户常用的屏幕录制工具&#xff0c;可是一旦录制结束&#xff0c;许多人不清楚如何找到和管理录制的视频文件。那么&#xff0c;您知道qq录屏保存到哪了吗&#xff1f;本文将深入研究qq录制视频功能&#xff0c;以帮助您了解如何存储和管理这些重要的录制视频文件…

网络爬虫(Python:Selenium、Scrapy框架;爬虫与反爬虫笔记)

网络爬虫&#xff08;Python&#xff1a;Selenium、Scrapy框架&#xff1b;爬虫与反爬虫笔记&#xff09; SeleniumWebDriver 对象提供的相关方法定位元素ActionChains的基本使用selenium显示等待和隐式等待显示等待隐式等待 Scrapy&#xff08;异步网络爬虫框架&#xff09;Sc…

AIGC|LangChain新手入门指南,5分钟速读版!

如果你用大语言模型来构建AI应用&#xff0c;那你一定不可能绕过LangChain,LangChain是现在最热门的AI应用框架之一&#xff0c;去年年底才刚刚发布&#xff0c;它在github上已经有了4.6万颗星的点赞了&#xff0c;在github社区上&#xff0c;每天都有众多大佬&#xff0c;用它…