《级联年度选择》一、List使用指南

HarmonyOS ArkTS List 列表组件使用指南

本文基于 HarmonyOS NEXT 开发环境,详细讲解 ArkTS 中 List 列表容器组件的核心概念、常用 API 及实战用法。通过一个完整的简约示例,帮助你从零掌握 List 组件的开发流程。


效果

一、List 组件概述

1.1 什么是 List

List是 ArkUI 框架提供的列表容器组件,用于包含一系列相同宽度的列表项(ListItem)。它天然支持滚动,适合连续、多行呈现同类数据,例如联系人列表、消息列表、商品清单等。

核心特性:

特性说明
自动滚动子项高度超出容器时自动出现滚动效果
子组件限制仅支持ListItemListItemGroup及自定义组件
布局方向默认垂直排列,可通过listDirection设为水平
数据驱动配合ForEach/LazyForEach实现动态渲染

1.2 基本结构

List(){ListItem(){Text('列表项 1')}ListItem(){Text('列表项 2')}ListItem(){Text('列表项 3')}}

注意:每个ListItem内部只能有一个根节点组件。如果需要多个组件组合,必须将它们包裹在RowColumnFlex等容器组件内。


二、核心 API 详解

2.1 构造参数

参数类型说明
spacenumber | string | Resource列表项之间的间距
initialIndexnumber初始显示的列表项索引
scrollerScroller可滚动组件的控制器,用于程序化控制滚动

2.2 常用属性

属性说明
.listDirection(direction)排列方向:Axis.Vertical(默认)或Axis.Horizontal
.scrollBar(state)滚动条状态:BarState.On/BarState.Off/BarState.Auto
.alignListItem(align)列表项对齐方式:ListItemAlign.Start/Center/End
.cachedCount(count)列表项缓存数量,优化长列表滚动性能
.layoutWeight(weight)在父容器中按权重分配剩余空间
.divider(divider)列表项之间的分割线样式
.edgeEffect(effect)滑动到边缘时的效果:EdgeEffect.Spring/None

2.3 常用事件

事件说明
.onAppear()列表项首次出现时触发
.onDisAppear()列表项消失时触发
.onScrollIndex(index)滑动到指定索引时触发
.onReachStart()滑动到列表顶部时触发
.onReachEnd()滑动到底部时触发

三、动态渲染:ForEach 与 LazyForEach

3.1 ForEach 循环渲染

ForEach是声明式循环渲染函数,它遍历数据源并为每一项创建对应的ListItem。当数据源与@State联动时,数据变化会自动触发 UI 刷新。

@Stateitems:string[]=['苹果','香蕉','橙子']List(){ForEach(this.items,(item:string)=>{ListItem(){Text(item).fontSize(16)}})}

ForEach 三个参数说明:

参数说明
arr数据源数组
itemGenerator列表项生成函数(item, index) => void
keyGenerator唯一键生成函数(item, index) => string(可选但推荐)

最佳实践:始终提供keyGenerator,它可以帮助框架精确识别数据变化,避免不必要的组件重建,提升性能。

3.2 LazyForEach 懒加载

当列表数据量很大时,使用LazyForEach配合IDataSource接口实现按需加载,只渲染可见区域的列表项,大幅提升性能。

List(){LazyForEach(this.dataSource,(item:DataItem)=>{ListItem(){Text(item.title)}},(item:DataItem)=>item.id.toString())}.cachedCount(5)// 缓存屏幕外 5 个列表项

四、分组列表:ListItemGroup

ListItemGroup用于将列表项分组显示,配合sticky属性可实现分组标题吸顶效果。

List(){ListItemGroup({header:this.groupHeader('水果')}){ForEach(this.fruits,(item:string)=>{ListItem(){Text(item)}})}ListItemGroup({header:this.groupHeader('蔬菜')}){ForEach(this.vegetables,(item:string)=>{ListItem(){Text(item)}})}}.sticky(StickyStyle.Header)@BuildergroupHeader(title:string){Text(title).fontSize(16).fontWeight(FontWeight.Bold).backgroundColor('#F5F5F5').width('100%').padding(12)}

五、完整实战示例:课程清单

下面通过一个完整的示例,演示如何使用 List 组件构建一个课程清单页面。

5.1 效果说明

  • 顶部显示标题栏
  • 中间使用 List 展示课程列表,每项包含课程名称、讲师和时长
  • 支持滚动、分割线显示
  • 列表项带有选中高亮效果

5.2 完整代码

// 数据模型classCourseItem{id:numbername:stringteacher:stringduration:stringconstructor(id:number,name:string,teacher:string,duration:string){this.id=idthis.name=namethis.teacher=teacherthis.duration=duration}}@Entry@Componentstruct CourseListPage{@StateselectedIndex:number=-1@StatecourseList:CourseItem[]=[newCourseItem(0,'HarmonyOS 应用开发入门','张老师','45分钟'),newCourseItem(1,'ArkTS 语言基础','李老师','60分钟'),newCourseItem(2,'ArkUI 组件详解','王老师','50分钟'),newCourseItem(3,'状态管理进阶','赵老师','55分钟'),newCourseItem(4,'路由与导航','孙老师','40分钟'),newCourseItem(5,'网络请求与数据持久化','周老师','65分钟'),newCourseItem(6,'性能优化实战','吴老师','70分钟'),]build(){Column(){// 标题栏Text('课程清单').fontSize(22).fontWeight(FontWeight.Bold).width('100%').padding({left:16,top:16,bottom:12})// 列表区域List({space:0}){ForEach(this.courseList,(item:CourseItem,index:number)=>{ListItem(){Row(){// 序号圆圈Text(`${index+1}`).fontSize(14).fontColor(Color.White).width(28).height(28).borderRadius(14).backgroundColor('#4FC3F7').textAlign(TextAlign.Center)// 课程信息Column(){Text(item.name).fontSize(16).fontWeight(FontWeight.Medium).maxLines(1).textOverflow({overflow:TextOverflow.Ellipsis})Row({space:12}){Text(`讲师:${item.teacher}`).fontSize(13).fontColor('#888888')Text(`时长:${item.duration}`).fontSize(13).fontColor('#888888')}.margin({top:4})}.layoutWeight(1).alignItems(HorizontalAlign.Start).margin({left:12})}.width('100%').padding({left:16,right:16,top:12,bottom:12}).backgroundColor(this.selectedIndex===item.id?'#E3F2FD':Color.White)}.onClick(()=>{this.selectedIndex=item.id})},(item:CourseItem)=>item.id.toString())}.width('100%').layoutWeight(1).scrollBar(BarState.Off).edgeEffect(EdgeEffect.Spring).divider({strokeWidth:0.5,color:'#E0E0E0',startMargin:56,endMargin:16})}.width('100%').height('100%').backgroundColor('#FAFAFA')}}

5.3 关键代码解析

(1)数据驱动渲染

使用@State装饰courseList数组,配合ForEach实现数据驱动的列表渲染。当数组发生变化时,UI 会自动刷新。

(2)选中状态高亮

通过@State selectedIndex记录当前选中的课程 ID,在ListItem中根据this.selectedIndex === item.id动态设置背景色。

(3)分割线配置

.divider({strokeWidth:0.5,color:'#E0E0E0',startMargin:56,// 左侧留白,与序号圆圈对齐endMargin:16})

startMarginendMargin让分割线不与序号圆圈重叠,视觉上更加整洁。

(4)边缘回弹效果

.edgeEffect(EdgeEffect.Spring)为列表添加了弹性回弹效果,提升用户的滑动体验。


六、最佳实践总结

6.1 性能优化

优化手段说明
使用LazyForEach大数据量列表按需加载,避免一次性创建所有组件
设置cachedCount缓存屏幕外的列表项,减少快速滑动时的创建开销
提供keyGenerator帮助框架精确识别变化项,减少不必要的组件重建
避免在ListItem中使用复杂嵌套减少布局层级,提升渲染速度

6.2 常见问题

问题原因及解决方案
列表项不显示检查ListItem内是否只有一个根节点组件
数据更新后 UI 不刷新使用@State装饰数据源,或通过keyGenerator精确控制刷新
滚动不流畅使用LazyForEach替代ForEach,设置合理的cachedCount
水平列表无法滚动确保设置了.listDirection(Axis.Horizontal)且有足够宽度

6.3 使用建议

  1. 简单列表用ForEach:数据量在几十条以内,直接使用ForEach即可。
  2. 长列表用LazyForEach:数据量较大时,配合IDataSource接口实现懒加载。
  3. 分组场景用ListItemGroup:配合sticky属性实现吸顶效果,适合通讯录、分类列表等场景。
  4. 善用ListScroller:通过scroller参数可以在代码中控制列表滚动到指定位置。

七、参考链接

  • List 官方 API 文档
  • ForEach 循环渲染
  • LazyForEach 懒加载