Harmony开发之循环渲染与条件渲染——动态列表的实现
引入:聊天消息列表场景
在日常应用中,我们经常需要展示动态数据列表,比如聊天消息、商品列表、新闻资讯等。这些场景的共同特点是:数据量可能很大,需要根据数据状态动态渲染不同的UI组件。在HarmonyOS开发中,ForEach循环渲染和if/else条件渲染正是解决这类问题的核心工具。
一、ForEach循环渲染
核心概念
ForEach接口基于数组类型数据进行循环渲染,需要与容器组件配合使用。它会在首次渲染时加载数据源的所有数据,并为每个数据项创建对应的组件。
基本用法
// 文件:pages/Index.ets
@Entry
@Component
struct MessageList {
@State messageList: Array<string> = ['你好', '今天天气不错', '晚上一起吃饭吗?']
build() {
List() {
ForEach(this.messageList, (item: string, index: number) => {
ListItem() {
Text(item)
.fontSize(18)
.margin({ top: 10, bottom: 10 })
}
}, (item: string) => item) // 键值生成器
}
.width('100%')
.height('100%')
}
}
键值生成规则
ForEach会为每个数组元素生成唯一键值,用于标识对应的组件。当键值变化时,框架会基于新键值创建新组件。
// 自定义键值生成器
ForEach(this.messageList, (item: string, index: number) => {
ListItem() {
Text(item)
}
}, (item: string, index: number) => `${index}_${item}`)
二、if/else条件渲染
核心概念
条件渲染可根据应用的不同状态,使用if、else和else if渲染对应状态下的UI内容。@State定义的变量归父组件所有,子组件通过@Link装饰器引用状态。
基本用法
// 文件:pages/Index.ets
@Entry
@Component
struct ChatPage {
@State hasNewMessage: boolean = true
@State messageType: string = 'text' // text | image | video
build() {
Column() {
// 条件渲染新消息提示
if (this.hasNewMessage) {
Text('有新消息')
.backgroundColor('#ff4757')
.fontColor(Color.White)
.padding(10)
}
// 多条件分支
if (this.messageType === 'text') {
Text('这是一条文本消息')
} else if (this.messageType === 'image') {
Image($r('app.media.message_image'))
.width(200)
.height(200)
} else {
Text('视频消息')
}
}
}
}
三、综合实战:聊天消息列表
数据结构定义
// 文件:model/Message.ts
export class Message {
id: string = ''
content: string = ''
type: string = 'text' // text | image | system
time: string = ''
isMine: boolean = false
status: string = 'sending' // sending | sent | failed
}
完整实现
// 文件:pages/ChatDetail.ets
import { Message } from '../model/Message'
@Entry
@Component
struct ChatDetail {
@State messageList: Array<Message> = [
{ id: '1', content: '你好', type: 'text', time: '10:30', isMine: false, status: 'sent' },
{ id: '2', content: '今天天气不错', type: 'text', time: '10:31', isMine: true, status: 'sent' },
{ id: '3', content: '晚上一起吃饭吗?', type: 'text', time: '10:32', isMine: false, status: 'sent' }
]
build() {
List() {
ForEach(this.messageList, (item: Message) => {
ListItem() {
// 根据消息类型和发送者渲染不同样式
if (item.isMine) {
this.MyMessage(item)
} else {
this.FriendMessage(item)
}
}
}, (item: Message) => item.id)
}
.width('100%')
.height('100%')
}
@Builder
MyMessage(item: Message) {
Column() {
Text(item.content)
.fontSize(16)
.backgroundColor('#007AFF')
.fontColor(Color.White)
.padding(10)
.borderRadius(10)
// 消息状态
if (item.status === 'sending') {
Text('发送中...')
.fontSize(12)
.fontColor('#666')
} else if (item.status === 'failed') {
Text('发送失败')
.fontSize(12)
.fontColor('#ff3b30')
}
}
.alignItems(HorizontalAlign.End)
.margin({ right: 10 })
}
@Builder
FriendMessage(item: Message) {
Column() {
Text(item.content)
.fontSize(16)
.backgroundColor('#E5E5EA')
.padding(10)
.borderRadius(10)
}
.alignItems(HorizontalAlign.Start)
.margin({ left: 10 })
}
}
四、性能优化建议
- 合理使用键值生成器:确保键值唯一且稳定,避免使用索引作为唯一键值
- 避免嵌套过深:条件渲染嵌套层数不宜过多,否则会影响性能
- 数据量控制:对于超长列表,建议使用LazyForEach懒加载组件
- 组件复用:使用@Builder构建可复用组件,减少重复代码
总结
ForEach循环渲染和if/else条件渲染是HarmonyOS开发中处理动态数据的核心能力。ForEach负责遍历数据源并生成对应的UI组件,而条件渲染则根据数据状态动态展示不同的UI内容。两者结合使用,可以轻松实现复杂的动态列表场景,如聊天消息、商品列表、新闻资讯等。
行动建议:
- 在开发列表页面时,优先考虑使用ForEach进行数据遍历
- 根据业务需求合理使用条件渲染,避免过度嵌套
- 注意键值生成规则,确保组件能够正确复用
- 对于大数据量场景,及时采用LazyForEach进行性能优化

浙公网安备 33010602011771号