目录
[1. 最简单的List](#1. 最简单的List)
[2. 自定义组件](#2. 自定义组件)
[3. 滚动控制](#3. 滚动控制)
[1. 分组列表](#1. 分组列表)
[2. 懒加载](#2. 懒加载)
[3. 下拉刷新与上拉加载](#3. 下拉刷新与上拉加载)
引言
在鸿蒙(HarmonyOS)应用开发中,List组件是最常用的UI组件之一,用于展示垂直滚动的列表数据。本文将详细介绍List组件的特性、使用方法以及一些实用技巧。
1.List组件基础
列表是一种复杂的容器,当列表项达到一定数量,内容超过屏幕大小时,可以自动提供滚动功能。它适合用于呈现同类数据类型或数据类型集,例如图片和文本。在列表中显示数据集合是许多应用程序中的常见要求(如通讯录、音乐列表、购物清单等)。
List是鸿蒙OS中用于展示垂直滚动列表的容器组件,具有以下特点:
-
高性能的列表渲染
-
支持大数据量的流畅滚动
-
内置多种布局和交互效果
-
支持分组和多种列表项样式
2.List接口参数
当我们创建 List 的时候,有三个默认可选参数,分别是 space、initialIndex、scroller。
我们分别看看他们的属性。
1.space
space 用来设置子组件主轴方向的间隔。

图1.space属性
2.initialIndex
设置当前 List初次加载的时候,初始 item 的索引值。

图2.修改初次加载显示的数据元素下标
3.scroller
可以滚动组件的控制器。
我们可以调用scroll的相关方法处理List。
例如我们可以通过下面的代码把List滚动到底部
TypeScript
Button("滚动到底部").onClick(()=>{
this.scroller.scrollEdge(Edge.Bottom)
})
3.ListView的属性
1.listDirection
设置List组件的排列方向。
listDirection是Axis类型的枚举,定义如下:
declare enum Axis {
Vertical,
Horizontal
}
默认值为Axis.Vertical,方向为纵向。
Axis.Horizontal方向为横向。
2.lanes
设置List组件的布局列数或者行数。
lanes
是鸿蒙(HarmonyOS)中List组件的一个重要属性,用于控制列表在水平方向上的布局方式,特别适用于需要多列布局的场景。通过设置lanes属性,可以让List组件中的列表项以网格形式排列,而不是传统的单列垂直排列。
3.divider
设置ListItem分割线样式,默认无分割线。
4.scrollBar
设置滚动条状态。
BarState.AutoAuto:按需显示
BarState.AutoOff:不显示
BarState.AutoOn:常驻显示
4.布局与约束
列表作为一种容器,会自动按其滚动方向排列子组件,向列表中添加组件或从列表中移除组件会重新排列子组件。
如下图所示,在垂直列表中,List按垂直方向自动排列ListItemGroup或ListItem。
ListItemGroup用于列表数据的分组展示,其子组件也是ListItem。ListItem表示单个列表项,可以包含单个子组件。

图3.List、ListItemGroup和ListItem组件关系
5.ListItem生命周期
1.使用ForEach创建ListItem
List组件创建时,所有ListItem将会被创建。显示区域内的ListItem在首帧进行布局,预加载范围内的ListItem在空闲时完成布局。预加载范围之外的ListItem仅创建ListItem自身,ListItem其内部的子组件不会被创建。
当List组件滑动时,进入预加载及显示区域的ListItem将会创建其内部的子组件并完成布局,而滑出预加载及显示区域的ListItem将不会被销毁。

图4.ForEach创建ListItem
2.使用LazyForEach创建ListItem
List组件创建时,显示区域中的ListItem会被创建与布局。预加载范围内的ListItem在空闲时创建与布局,但是不会被挂载到组件树上。预加载范围外的ListItem则不会被创建。
当List组件滑动时,进入预加载及显示区域的ListItem将被创建与布局,创建ListItem过程中,若ListItem内部如果包含@Reusable标记的自定义组件,则会优先从缓存池中复用。滑出预加载及显示区域的ListItem将被销毁,其内部若含@Reusable标记的自定义组件,则会被回收并加入缓存池。

图5.LazyForEach创建ListItem的生命周期
3.使用Repeat创建ListItem
1.使用virtualScroll
List组件创建时,显示区域内的ListItem将被创建和布局。预加载范围内的ListItem在空闲时创建和布局,并且挂载至组件树上。预加载范围外的ListItem则不会被创建。
当List组件滑动时,进入预加载及显示区域的ListItem,将从缓存池中获取ListItem并复用及布局,若缓存池中无ListItem,则会新创建并布局。滑出预加载及显示区域的ListItem会将被回收至缓存池。

图6.Repeat使用virtualScroll创建ListItem的生命周期
2.不使用virtualScroll
List组件创建时,所有ListItem均被创建。显示区域内的ListItem在首帧完成布局,预加载范围内的ListItem在空闲时完成布局。预加载范围外的ListItem不会进行布局。
当List组件滑动时,进入预加载及显示区域的ListItem将进行布局。滑出预加载及显示区域的ListItem不会销毁。

图7.Repeat不使用virtualScroll创建ListItem的生命周期
1.listDirection
1.listDirection
// 示例代码:基本List使用
import { List, ListItem } from '@ohos/arkui';
@Entry
@Component
struct MyList {
private data: string[] = ['苹果', '香蕉', '橙子', '葡萄', '西瓜']
build() {
Column() {
List({ space: 20 }) {
ForEach(this.data, (item: string) => {
ListItem() {
Text(item)
.fontSize(20)
.margin({ left: 15 })
}
})
}
.width('100%')
.height('100%')
}
}
}
6.List的使用场景
1. 最简单的List
在最简单的列表形式中,List静态地创建其列表项ListItem的内容。
当我们ListView的ListItem只有一个组件的时候,我们使用下面的代码即可实现一个简单的列表。
TypeScript
@Entry
@Component
struct CityList {
build() {
NavDestination(){
List() {
ListItem(){
Text('北京').fontSize(24)
}
ListItem(){
Text('上海').fontSize(24)
}
ListItem(){
Text('杭州').fontSize(24)
}
} .backgroundColor('#FFF1F3F5')
.alignListItem(ListItemAlign.Center)
}.title("List实现城市列表")
}
}
效果图如下:

图8.最简单的List
@State private messages: Message[] = [
{ id: 1, content: '你好鸿蒙' },
{ id: 2, content: 'List组件学习' },
// 更多数据...
];
List() {
ForEach(this.messages, (item: Message) => {
ListItem() {
Text(item.content)
}
})
}
2. 自定义组件
因此,如果ListItem是由多个组件元素组成的,则需要将这多个元素组合到一个容器组件内或组成一个自定义组件。
例如我们要实现一个通讯录联系人页面:

图9.联系人列表
如上图所示,联系人列表的列表项中,每个联系人都有头像和名称。此时,需要将Image和Text封装到一个Row容器内。
TypeScript
List() {
ListItem() {
Row() {
// app.media.iconE为自定义资源
Image($r('app.media.iconE'))
.width(40)
.height(40)
.margin(10)
Text('小明')
.fontSize(20)
}
}
ListItem() {
Row() {
// app.media.iconF为自定义资源
Image($r('app.media.iconF'))
.width(40)
.height(40)
.margin(10)
Text('小红')
.fontSize(20)
}
}
}
3. 滚动控制
private scroller: Scroller = new Scroller()
List({ scroller: this.scroller }) {
// 列表内容
}
// 滚动到指定位置
this.scroller.scrollTo({ x: 0, y: 100 })
高级特性
1. 分组列表
List() {
ForEach(this.groupData, (group: Group) => {
ListItemGroup({ header: this.GroupHeader(group.name) }) {
ForEach(group.items, (item: Item) => {
ListItem() {
Text(item.name)
}
})
}
})
}
2. 懒加载
List() {
LazyForEach(this.dataSource, (item: Item) => {
ListItem() {
Text(item.name)
}
})
}
3. 下拉刷新与上拉加载
List({ controller: this.listController }) {
// 列表内容
}
.onRefresh(() => {
// 下拉刷新逻辑
})
.onReachEnd(() => {
// 上拉加载更多
})
性能优化技巧
-
复用列表项:确保ListItem的结构尽可能简单,提高复用率
-
避免复杂计算:在列表渲染中避免复杂的计算和频繁的UI更新
-
使用LazyForEach:对于大数据集,使用LazyForEach代替ForEach
-
图片懒加载:列表中的图片使用懒加载技术
常见问题解决
-
列表滚动卡顿:
-
检查是否有过多的UI更新
-
确保使用了正确的数据绑定方式
-
考虑分页加载数据
-
-
列表项点击无响应:
-
检查是否添加了.onClick事件
-
确保没有其他组件遮挡了点击区域
-
-
列表数据显示异常:
-
检查数据源是否正确更新
-
确认ForEach或LazyForEach的key值唯一且稳定
-
结语
List组件是鸿蒙应用开发中不可或缺的重要组件,掌握其使用方法和优化技巧对于构建流畅的用户界面至关重要。通过本文的介绍,希望您能更高效地使用List组件,为您的鸿蒙应用带来更好的用户体验。
在实际开发中,建议多参考鸿蒙官方文档和示例代码,不断实践和优化您的列表实现。