ArkTS四种渲染控制能力

embedded/2024/11/28 7:30:26/

大家好,我是 V 哥。ArkTS 是 OpenHarmony 框架的一部分,提供了声明式 UI 渲染的能力。下面来对ArkTS中四种渲染控制能力: if/elseForEachLazyForEachContentSlot 详细介绍一下:

1. if/else 渲染控制

if/else 是 ArkTS 提供的基本逻辑控制语法,用于 基于条件动态控制组件的渲染。它的核心用途是根据某些条件,在运行时决定渲染哪些组件,以及组件的结构或内容。以下是它的主要特点和用途的详细介绍:

主要用途
  1. 动态显示或隐藏组件

    • 根据变量的值,动态控制某些组件是否渲染。
    • 避免不必要的组件渲染,提高性能。
  2. 实现多种状态的界面切换

    • 适合条件分支较少的场景。
    • 在界面上根据状态显示不同的布局或信息(如登录状态、加载中状态、错误提示等)。
  3. 响应用户交互或数据变化

    • 基于用户的操作动态更新界面。
    • 如点击按钮后切换视图,或数据加载完成后切换显示内容。
  4. 个性化内容显示

    • 根据用户角色、权限或其他业务逻辑,动态展示不同的组件或内容。

详细讲解

语法基础

  • if/else 语法与普通编程语言一致,可以嵌套其他 ArkTS UI 组件。
  • if 用于条件成立时渲染的组件,else 用于条件不成立时的渲染。

示例场景与代码

场景 1:登录状态控制

根据用户是否登录,显示欢迎信息或登录提示。

@Entry
@Component
struct LoginExample {private isLoggedIn: boolean = false;build() {Column() {// 根据用户登录状态显示不同的内容if (this.isLoggedIn) {Text("欢迎回来,用户!").fontSize(20).padding(10)} else {Text("您尚未登录,请登录继续操作").fontSize(16).padding(10)Button("登录") {this.isLoggedIn = true; // 登录后更新状态}.padding(5)}}}
}
场景 2:加载状态切换

显示加载中的动画或加载完成后的内容。

@Entry
@Component
struct LoadingExample {private isLoading: boolean = true;build() {Column() {// 判断当前是否为加载状态if (this.isLoading) {Text("加载中,请稍候...").fontSize(18).padding(10)} else {Text("内容加载完成!").fontSize(18).padding(10)}// 模拟状态切换按钮Button("切换状态") {this.isLoading = !this.isLoading; // 切换加载状态}.padding(10)}}
}
场景 3:权限显示

根据用户权限等级展示不同的内容。

@Entry
@Component
struct PermissionExample {private userRole: string = "guest"; // 用户角色:guest, user, adminbuild() {Column() {if (this.userRole === "guest") {Text("欢迎游客,请注册以享受更多功能。").fontSize(16).padding(10)} else if (this.userRole === "user") {Text("欢迎普通用户,解锁更多高级功能升级为管理员。").fontSize(16).padding(10)} else if (this.userRole === "admin") {Text("欢迎管理员,您拥有最高权限!").fontSize(16).padding(10)}// 模拟权限切换按钮Row() {Button("设置为游客") { this.userRole = "guest" }.padding(5)Button("设置为普通用户") { this.userRole = "user" }.padding(5)Button("设置为管理员") { this.userRole = "admin" }.padding(5)}}}
}

if/else 使用时的注意事项
  1. 避免复杂嵌套

    • 嵌套层级过深会影响代码的可读性,建议将复杂逻辑拆分成方法或子组件。
  2. 性能优化

    • if/else 不会渲染未满足条件的组件,因此可以利用该特性控制渲染数量,避免浪费资源。
  3. 配合状态管理

    • 可以结合 State@Observed 数据模型,实现更灵活的动态渲染。

if/else 是 ArkTS 中最基础的控制语法,通过动态切换组件的渲染路径,可以灵活应对各种场景下的界面需求,使开发者能够快速实现逻辑清晰、性能优异的动态 UI。


2. ForEach 渲染控制

ForEach 是 ArkTS 提供的一种迭代语法,专用于遍历固定或小规模的数据集合,并基于集合的每个元素动态生成 UI 组件。它在开发中扮演着重要角色,尤其是需要根据数组或列表生成界面内容时。

主要用途
  1. 动态渲染组件列表

    • 根据数据集合的元素,生成对应的组件。
    • 适合中小规模的静态或动态数据集合。
  2. 数据驱动的视图更新

    • 数据集合发生改变(增删改)时,ForEach 会自动更新渲染内容,保证视图与数据同步。
  3. 可配置的动态视图

    • 使用相同的组件模板,为不同的数据生成独特的内容或样式。
  4. 清晰的逻辑分离

    • 数据与视图逻辑解耦,通过数据集合定义 UI,避免手动创建多个类似组件。

语法

基本语法

ForEach(array, (item) => {// 渲染逻辑
})

参数

  • array:要遍历的数组或集合。
  • (item):当前元素的引用,可用于组件内容的动态生成。

示例与场景讲解

场景 1:简单列表渲染

示例:展示水果名称的简单列表。

@Entry
@Component
struct SimpleListExample {private fruits: string[] = ["苹果", "香蕉", "橘子", "葡萄"];build() {Column() {ForEach(this.fruits, (fruit) => {Text(fruit).fontSize(20).padding(5)})}}
}

解析

  • 遍历 fruits 数组,动态生成每个 Text 组件。
  • fruits 数组发生变化时(增删项),界面会自动更新。

场景 2:带索引的列表渲染

示例:显示带序号的城市列表。

@Entry
@Component
struct IndexedListExample {private cities: string[] = ["北京", "上海", "广州", "深圳"];build() {Column() {ForEach(this.cities, (city, index) => {Text(`${index + 1}. ${city}`).fontSize(18).padding(5)})}}
}

解析

  • 使用 index 显示当前元素的序号。
  • 可以动态绑定索引值到 UI。

场景 3:复杂数据对象渲染

示例:渲染用户信息卡片。

interface User {name: string;age: number;
}@Entry
@Component
struct UserListExample {private users: User[] = [{ name: "张三", age: 25 },{ name: "李四", age: 30 },{ name: "王五", age: 28 }];build() {Column() {ForEach(this.users, (user) => {Column() {Text(`姓名:${user.name}`).fontSize(18)Text(`年龄:${user.age}`).fontSize(16).padding(2)}.padding(10).border(Color.Gray, 1).margin(5)})}}
}

解析

  • 遍历 users 数组,每个元素生成一个用户信息卡片。
  • 通过 Column 嵌套展示每个用户的属性信息。

场景 4:动态列表(增删项)

示例:实现可以增删项目的任务列表。

@Entry
@Component
struct DynamicListExample {private tasks: string[] = ["完成报告", "开会", "整理资料"];build() {Column() {// 渲染任务列表ForEach(this.tasks, (task, index) => {Row() {Text(task).fontSize(18).padding(5)Button("删除") {this.tasks.splice(index, 1); // 删除对应任务}.padding(5)}})// 添加新任务的输入框和按钮Row() {TextField({ placeholder: "输入新任务" }).onChange((value) => {this.newTask = value;}).width('70%')Button("添加任务") {if (this.newTask.trim() !== "") {this.tasks.push(this.newTask.trim());}}.padding(5)}.margin(10)}}private newTask: string = ""; // 输入的新任务内容
}

解析

  • 使用 ForEach 渲染 tasks 列表。
  • tasks 数据更新时,UI 会同步变更。
  • 提供输入框和按钮以动态添加或删除任务。

注意事项
  1. 适用于小规模数据集合

    • ForEach 适合几百条以内的数据,数据量特别大时建议使用 LazyForEach
  2. 保持数据唯一性

    • 遍历的数据集合应尽量保持唯一标识(如索引或 ID),避免意外更新或视图错乱。
  3. 避免过深嵌套

    • 如果 ForEach 嵌套过多,可能导致代码不易维护,建议拆分为子组件。

通过 ForEach 渲染控制,开发者能够快速生成基于数据的动态 UI,满足各种场景下的灵活需求,从静态内容到动态交互都可以轻松实现。

3. LazyForEach 渲染控制

LazyForEach 是 ArkTS 提供的一种高效迭代语法,专为 大规模、动态数据集合 设计,通过 延迟加载 的机制,按需渲染可见范围内的组件,从而显著提高性能。

主要用途
  1. 大规模数据的高效渲染

    • 当数据集合规模较大(如数千条以上),LazyForEach 能避免一次性加载所有组件,从而节省内存和渲染时间。
  2. 按需加载数据

    • 根据当前视图的可见范围,仅渲染需要显示的内容,未进入视图的部分不会占用计算资源。
  3. 支持动态增删数据

    • 当数据集合动态变化(增删、更新)时,LazyForEach 会自动优化渲染流程,保持性能稳定。
  4. 流畅的用户体验

    • 在需要滚动查看长列表(如聊天记录、商品列表)时,延迟加载机制保证了操作的流畅性。

语法

先来看一下基本语法

LazyForEach(array, (item, index) => {// 渲染逻辑
})

参数

  • array:需要遍历的大规模数据集合。
  • (item, index):当前数据元素及其索引,传递给渲染逻辑。

示例与场景讲解

场景 1:大规模数据的列表渲染

示例:显示 1,000 条用户消息记录。

@Entry
@Component
struct LargeDataExample {private messages: string[] = Array.from({ length: 1000 }, (_, i) => `消息 ${i + 1}`);build() {LazyForEach(this.messages, (message) => {Text(message).fontSize(18).padding(5)})}
}

解析

  • 数据集合 messages 包含 1,000 条消息。
  • LazyForEach 会根据可见范围按需渲染消息内容,减少一次性渲染的负担,保证性能流畅。

场景 2:动态加载商品列表

示例:实现商品列表的无限滚动加载。

@Entry
@Component
struct InfiniteScrollExample {private products: string[] = Array.from({ length: 20 }, (_, i) => `商品 ${i + 1}`);private pageCount: number = 1;build() {Column() {LazyForEach(this.products, (product) => {Text(product).fontSize(16).padding(10)})Button("加载更多") {this.loadMoreProducts(); // 加载更多商品}.padding(10)}}private loadMoreProducts() {// 模拟每次加载 20 个商品this.pageCount += 1;const newProducts = Array.from({ length: 20 }, (_, i) => `商品 ${i + 1 + this.products.length}`);this.products.push(...newProducts);}
}

解析

  • 初始数据为 20 个商品,点击按钮后动态加载更多商品。
  • LazyForEach 按需渲染新增的内容,保持性能稳定。

场景 3:聊天消息界面

示例:渲染实时更新的聊天消息。

@Entry
@Component
struct ChatExample {private messages: { sender: string; content: string }[] = [{ sender: "用户A", content: "你好" },{ sender: "用户B", content: "你好!有事吗?" }];build() {LazyForEach(this.messages, (message) => {Column() {Text(`${message.sender}`).fontSize(14).fontWeight(FontWeight.Bold).padding(2)Text(message.content).fontSize(16).padding(5)}.padding(10).border(Color.Gray, 1).margin(5)})}addMessage(sender: string, content: string) {this.messages.push({ sender, content });}
}

解析

  • 聊天消息实时追加到数据集合 messages 中。
  • LazyForEach 仅渲染当前可见区域的消息,确保滚动和渲染的流畅性。

场景 4:渲染含图片的大规模数据

示例:展示 500 张商品图片列表。

@Entry
@Component
struct ImageGridExample {private images: string[] = Array.from({ length: 500 }, (_, i) => `https://example.com/image${i + 1}.jpg`);build() {LazyForEach(this.images, (imageUrl) => {Image(imageUrl).width(100).height(100).margin(5)})}
}

解析

  • 渲染图片时内存消耗较高,LazyForEach 可以有效避免加载所有图片造成的卡顿。
  • 仅在用户滚动到图片所在位置时加载对应内容。

LazyForEach 的优势

  1. 性能优化

    • 避免一次性渲染整个数据集合,显著减少内存和 CPU 的占用。
    • 在数据规模较大时(如几千条以上),相比 ForEach 更高效。
  2. 按需更新

    • 渲染机制基于用户可见范围,动态更新界面内容。
  3. 适应动态数据

    • 动态增删数据集合中的元素时,LazyForEach 无需手动干预,即可自动优化。

注意事项

  1. 适用场景

    • 推荐:用于大规模数据集合(数百条及以上),如聊天记录、长列表、图片网格等。
    • 非必要:若数据规模较小(几百条以内),可以使用 ForEach,避免引入额外复杂性。
  2. 视图更新

    • 当数据集合变化较频繁时,确保数据的唯一标识(如索引或 ID)以避免视图错乱。
  3. 资源管理

    • 如果渲染内容包含较大的资源(如图片、视频),需要适当处理资源加载与释放。

LazyForEach 是 ArkTS 中不可或缺的渲染工具,它以延迟加载的机制为大规模动态数据集合的显示提供了性能保障,同时保证用户交互的流畅体验。在开发长列表或大规模数据的应用时,它能显著提高开发效率和应用性能。

4. ContentSlot 渲染控制

ContentSlot 是 ArkTS 提供的一种 插槽渲染机制,用于在组件中动态插入子组件内容。它允许父组件定义占位区域,子组件可以通过插槽填充动态内容。类似于前端开发中的 slotchildren 概念,ContentSlot 提高了组件的复用性和灵活性。

主要用途

  1. 组件内容动态填充

    • 通过占位插槽机制,父组件定义好插槽位置,具体内容由子组件或外部动态提供。
  2. 高复用性组件开发

    • 设计通用组件时,开发者可以通过插槽允许自定义内容插入,例如按钮、弹窗等。
  3. 父子组件的灵活传递

    • ContentSlot 使父组件与子组件的内容解耦,减少硬编码的限制。
  4. 提升内容扩展能力

    • 插槽内容可以根据需求灵活调整,适应不同场景的 UI 设计。

语法

定义插槽

ContentSlot("slotName", defaultContent)

填充插槽

Column() {CustomComponent {slotName: Text("我是WG")}
}
  • slotName:插槽的名称,父组件通过这个名称标识插槽位置。
  • defaultContent:默认显示的内容,如果未插入内容,将使用该内容。

示例与场景讲解

场景 1:动态按钮内容

示例:创建一个按钮组件,支持动态插入内容(如文本或图标)。

@Entry
@Component
struct ButtonWithSlot {build() {Column() {// 使用默认内容CustomButton()// 动态插入内容CustomButton {contentSlot: Text("提交").fontSize(18).fontWeight(FontWeight.Bold)}}}
}@Component
struct CustomButton {build() {Row().backgroundColor(Color.Blue).padding(10).alignItems(HorizontalAlign.Center).borderRadius(5) {ContentSlot("contentSlot", Text(" 点我一下试试").fontSize(16).color(Color.White))}}
}

解析

  • CustomButton 是一个通用按钮组件,使用 ContentSlot 定义插槽 contentSlot
  • 默认插槽内容为 “默认按钮”,外部可以动态插入不同的内容,如 “提交”。

场景 2:可扩展的弹窗组件

示例:实现一个通用弹窗,支持动态插入标题和内容。

@Entry
@Component
struct PopupWithSlotExample {private isVisible: boolean = true;build() {if (this.isVisible) {Popup {titleSlot: Text("弹窗标题:点了又能怎样").fontSize(20).fontWeight(FontWeight.Bold),contentSlot: Text("这是弹窗的内容:不怎么样,你赢了").fontSize(16).padding(10)}}}
}@Component
struct Popup {build() {Column().backgroundColor(Color.White).padding(20).borderRadius(10) {ContentSlot("titleSlot", Text("默认标题").fontSize(18).color(Color.Black))Divider().backgroundColor(Color.Gray).height(1).margin(10, 0)ContentSlot("contentSlot", Text("默认内容").fontSize(14).color(Color.Gray))}}
}

解析

  • Popup 是一个弹窗组件,定义了 titleSlotcontentSlot 两个插槽。
  • 父组件 PopupWithSlotExample 通过插槽填充标题和内容,外部组件可以灵活调整弹窗内容。

场景 3:动态卡片组件

示例:实现一个支持自定义图片和文字内容的卡片组件。

@Entry
@Component
struct CardSlotExample {build() {Card {imageSlot: Image("https://xxxxx.com/image.jpg").width(100).height(100),textSlot: Text("自定义卡片内容").fontSize(18).padding(10)}}
}@Component
struct Card {build() {Column().backgroundColor(Color.LightGray).padding(10).borderRadius(8).alignItems(HorizontalAlign.Center) {ContentSlot("imageSlot", Image("").width(50).height(50))ContentSlot("textSlot", Text("默认卡片内容").fontSize(16).color(Color.Black))}}
}

解析

  • Card 定义了 imageSlottextSlot,允许父组件动态插入图片和文字内容。
  • 父组件通过填充插槽,自定义卡片的具体显示内容。

ContentSlot 的优势

  1. 灵活性

    • 插槽内容完全由外部定义,组件可以适应多种使用场景。
  2. 高复用性

    • 通用组件开发中,通过 ContentSlot 提供内容插入点,大大提高组件的复用性。
  3. 内容解耦

    • 父组件负责插槽定义,子组件填充具体内容,减少代码耦合。
  4. 默认内容支持

    • 插槽未填充时,显示默认内容,保证组件的完整性和容错性。

注意事项

  1. 插槽命名

    • 插槽名称应具有描述性,避免重名导致内容错乱。
  2. 默认内容设置

    • 始终为插槽提供默认内容,防止外部未填充时出现空白区域。
  3. 复杂嵌套场景

    • 在嵌套组件中使用 ContentSlot 时,保持插槽结构清晰,避免逻辑混乱。

ContentSlot 为 ArkTS 的组件设计提供了高度的扩展能力,开发者可以通过它实现动态化和模块化的组件设计。无论是按钮、弹窗,还是复杂的卡片组件,ContentSlot 都能让内容的插入变得简单而高效。


小结一下

控制方式功能典型应用场景
if/else条件控制渲染组件的显示与隐藏动态显示状态内容(如登录/未登录状态)
ForEach遍历小规模数据集合渲染组件渲染固定数量的列表
LazyForEach延迟渲染大规模数据集合动态加载的长列表(如消息、数据流)
ContentSlot支持动态插入子组件插槽设计,实现组件内容的动态拓展

我们可以充分利用 ArkTS 提供的声明式渲染控制能力,提升应用的灵活性与性能。关注威哥爱编程,鸿蒙千帆起。


http://www.ppmy.cn/embedded/141129.html

相关文章

第一章:Go 语言概述 2.安装和配置 Go 开发环境 --Go 语言轻松入门

第一章:Go 语言概述 2.安装和配置 Go 开发环境 --Go 语言轻松入门 安装和配置 Go 开发环境相对简单,以下是在不同操作系统上安装和配置 Go 的步骤: Windows 1. 下载 Go 安装包 访问 Go 下载。选择适用于 Windows 的安装包(通常…

11.27字节番茄小说后端实习OC面经

本帖暂时只介绍部分面试题及解析 1.介绍一下bean流程 本面试题其实就是考察spring的基础,鉴于是字节,所以还是答得详细一点比较好 Bean的启动流程是Spring框架中的核心机制之一,它基于依赖注入(Dependency Injection&#xff0…

动态规划子数组系列一>单词拆分

题目&#xff1a; 解析&#xff1a; 代码&#xff1a; public boolean wordBreak(String s, List<String> wordDict) {//优化⼀&#xff1a;将字典里面的单词放入哈希表&#xff0c;为后续找字串提高速度Set<String> hash new HashSet<>(wordDict);int n…

金融智能化的明日之星:量化交易模型的演化与发展

量化交易模型作为金融领域中的重要创新手段&#xff0c;已经从传统交易方式中脱颖而出&#xff0c;成为数据与算法驱动金融决策的核心工具。从简单的技术分析到复杂的多因子模型&#xff0c;再到融合人工智能与大数据的智能交易系统&#xff0c;量化模型的探索与发展推动了金融…

《物联网智能项目》

一、引言 随着科技的不断进步&#xff0c;物联网&#xff08;Internet of Things&#xff0c;IoT&#xff09;已经成为当今世界最具发展潜力的领域之一。物联网智能项目通过将各种设备、传感器和系统连接到互联网&#xff0c;实现了智能化的监测、控制和管理&#xff0c;为人们…

基于python+django+vue.js开发的停车管理系统

功能介绍 平台采用B/S结构&#xff0c;后端采用主流的Python语言进行开发&#xff0c;前端采用主流的Vue.js进行开发。 功能包括&#xff1a;车位管理、会员管理、停车场管理、违规管理、用户管理、日志管理、系统信息模块。 源码地址 https://github.com/geeeeeeeek/pytho…

通过DBUA升级 Oracle 11g到Oracle12c版本

Oracle 11g升级到Oracle12c Oracle11g数据库环境准备与数据备份 环境&#xff1a; oracle11.2.0.4 to oralce12.2.0.1 升级方案&#xff1a; 升级方案很多种&#xff0c;我们ORACLE培训课程第8阶段有所讲所有的升级方案&#xff0c;我们这里采用DBUA官方建议的方法 1、手…

记录一次在生产环境中更换 SSL 证书的操作

本文将记录一次在生产环境中更换 SSL 证书的过程&#xff0c;包括准备工作、遇到的问题和解决方案&#xff0c;以及如何重启和重新加载 Nginx 服务以使更改生效。 1. 确认证书过期 SSL 证书通常具有有效期&#xff0c;当证书过期时&#xff0c;用户访问网站时会看到浏览器警告…