引入:聊天消息列表場景
在日常應用中,我們經常需要展示動態數據列表,比如聊天消息、商品列表、新聞資訊等。這些場景的共同特點是:數據量可能很大,需要根據數據狀態動態渲染不同的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進行性能優化