OpenHarmony 网格、列表进阶与懒加载实战开发
·
承接前两篇 ArkUI 组件内容,本文聚焦Grid 网格布局、List 列表高阶用法、组件懒加载、瀑布流等高频实用能力,结合完整案例讲解特性、适配方案与性能优化,适合页面布局进阶开发。
一、概述
在应用开发中,图文宫格、商品陈列、相册、分类菜单等场景,传统 Row/Column 布局已无法满足需求。Grid网格组件专门实现多列排布,而List除基础列表外,还支持分组、下拉刷新、上拉加载;配合懒加载可以大幅优化长列表、多图页面的内存占用与渲染速度,是大型应用必备技术。
二、Grid 网格布局组件
Grid 用于实现行列规则排列的宫格布局,广泛应用于功能菜单、相册、商品列表、图标导航。搭配GridItem作为列表项使用。

2.1 基础网格(固定列数)
核心参数:columnsTemplate 定义列数与列宽,rowsTemplate 定义行数,columnGap/rowGap 设置行列间距。
@Entry
@Component
struct GridBasicDemo {
// 模拟宫格数据
gridData: string[] = ["首页", "分类", "购物车", "我的", "消息", "设置"]
build() {
Column({ space: 20 }) {
Text("基础4列网格布局").fontSize(20).fontWeight(FontWeight.Bold)
Grid() {
ForEach(this.gridData, (item: string) => {
GridItem() {
Column() {
// 模拟图标区域
Rect().width(50).height(50).fill("#007DFF").borderRadius(8)
Text(item).fontSize(16).margin({ top: 8 })
}
.width("100%")
.alignItems(HorizontalAlign.Center)
}
})
}
.columnsTemplate("1fr 1fr 1fr 1fr") // 均分4列
.columnGap(15)
.rowGap(20)
.width("100%")
}
.padding(20)
}
}
2.2 不等宽网格布局
通过不同比例 fr 单位,实现非均等分网格,适配复杂导航布局。
@Entry
@Component
struct GridUnequalDemo {
build() {
Column({ space: 20 }) {
Text("不等宽网格布局").fontSize(20).fontWeight(FontWeight.Bold)
Grid() {
GridItem() { Text("模块1").width("100%").height(80).textAlign(TextAlign.Center).backgroundColor("#87CEEB") }
GridItem() { Text("模块2").width("100%").height(80).textAlign(TextAlign.Center).backgroundColor("#98FB98") }
GridItem() { Text("模块3").width("100%").height(80).textAlign(TextAlign.Center).backgroundColor("#FFD700") }
}
.columnsTemplate("2fr 1fr 1fr") // 第一列宽度是后两列总和
.columnGap(10)
.width("100%")
}
.padding(20)
}
}
2.3 网格跨行列合并
通过 rowSpan、colSpan 实现单元格跨行、跨列,制作不规则宫格。
@Entry
@Component
struct GridSpanDemo {
build() {
Grid() {
// 跨2行
GridItem({ rowSpan: 2 }) {
Text("跨行2行")
.width("100%")
.height("100%")
.textAlign(TextAlign.Center)
.backgroundColor("#FFA07A")
}
GridItem() { Text("普通项1").width("100%").height(80).textAlign(TextAlign.Center).backgroundColor("#DDA0DD") }
GridItem() { Text("普通项2").width("100%").height(80).textAlign(TextAlign.Center).backgroundColor("#DDA0DD") }
// 跨2列
GridItem({ colSpan: 2 }) {
Text("跨列2列")
.width("100%")
.height(80)
.textAlign(TextAlign.Center)
.backgroundColor("#9370DB")
}
}
.columnsTemplate("1fr 1fr 1fr")
.rowGap(8)
.columnGap(8)
.width("100%")
.padding(20)
}
}
三、List 列表高阶用法
在前文基础上,拓展分组列表、下拉刷新、上拉加载三大实用功能,是资讯、聊天、商品列表的核心能力。
3.1 分组列表 ListItemGroup
用于实现带标题的分组列表,如通讯录、分类设置、多级菜单。
@Entry
@Component
struct ListGroupDemo {
build() {
List({ space: 5 }) {
// 第一组
ListItemGroup({ header: Text("常用功能").fontSize(18).fontWeight(FontWeight.Bold).padding(10) }) {
ListItem() { Text("账号管理").width("100%").height(45).padding({ left: 15 }) }
ListItem() { Text("安全中心").width("100%").height(45).padding({ left: 15 }) }
}
// 第二组
ListItemGroup({ header: Text("系统设置").fontSize(18).fontWeight(FontWeight.Bold).padding(10) }) {
ListItem() { Text("消息通知").width("100%").height(45).padding({ left: 15 }) }
ListItem() { Text("隐私权限").width("100%").height(45).padding({ left: 15 }) }
}
}
.width("100%")
.height("100%")
}
}
3.2 下拉刷新 + 上拉加载更多
结合 onRefresh、onReachEnd 实现列表动态刷新与分页加载,模拟网络请求场景
@Entry
@Component
struct ListLoadDemo {
@State listData: number[] = [1, 2, 3, 4, 5]
@State isRefreshing: boolean = false
// 下拉刷新
onRefresh() {
this.isRefreshing = true
setTimeout(() => {
this.listData = [1, 2, 3, 4, 5]
this.isRefreshing = false
}, 1500)
}
// 上拉加载
loadMore() {
let len = this.listData.length
for (let i = len + 1; i <= len + 5; i++) {
this.listData.push(i)
}
}
build() {
List({ space: 8 }) {
ForEach(this.listData, (item: number) => {
ListItem() {
Text(`列表条目 ${item}`)
.width("100%")
.height(50)
.textAlign(TextAlign.Start)
.padding({ left: 20 })
.backgroundColor("#F8F8F8")
}
})
}
.width("100%")
.height("100%")
.refresh({ refreshing: this.isRefreshing })
.onRefresh(() => this.onRefresh())
.onReachEnd(() => this.loadMore())
}
}
四、组件懒加载(LazyForEach)
普通 ForEach 会一次性渲染所有列表项,数据量大时易卡顿、占用内存高。LazyForEach 实现可视区域懒加载,仅渲染屏幕内条目,是长列表性能优化核心方案。
4.1 懒加载基础使用
需要自定义数据类实现 ICollectionData 接口,适配懒加载数据源规则。
// 实现懒加载数据源
class BasicDataSource implements ICollectionData {
private dataArr: string[]
constructor(arr: string[]) {
this.dataArr = arr
}
// 获取总数量
getTotalCount(): number {
return this.dataArr.length
}
// 获取单条数据
getData(index: number): string {
return this.dataArr[index]
}
// 数据变更通知
setDataChangeListener(listener: DataChangeListener): void {}
}
@Entry
@Component
struct LazyForEachDemo {
// 模拟100条数据
private dataSource: BasicDataSource = new BasicDataSource(
Array.from({ length: 100 }, (_, idx) => `懒加载条目 ${idx + 1}`)
)
build() {
List() {
LazyForEach(this.dataSource, (item: string) => {
ListItem() {
Text(item)
.width("100%")
.height(50)
.padding({ left: 20 })
.backgroundColor("#F5F5F5")
.margin({ bottom: 5 })
}
})
}
.width("100%")
.height("100%")
}
}
4.2 Grid 结合懒加载
大量图片 / 宫格页面,搭配 LazyForEach 大幅提升页面流畅度。
@Entry
@Component
struct GridLazyDemo {
private dataSource: BasicDataSource = new BasicDataSource(
Array.from({ length: 60 }, (_, idx) => `宫格 ${idx + 1}`)
)
build() {
Grid() {
LazyForEach(this.dataSource, (item: string) => {
GridItem() {
Column() {
Rect().width(60).height(60).fill("#4682B4").borderRadius(6)
Text(item).fontSize(14).margin({ top: 6 })
}
.width("100%")
.alignItems(HorizontalAlign.Center)
.padding(10)
}
})
}
.columnsTemplate("1fr 1fr 1fr")
.columnGap(12)
.rowGap(15)
.width("100%")
.padding(15)
}
}
五、综合实战:相册页面(Grid + 懒加载)
整合网格布局与懒加载,实现典型相册界面,可直接用于项目开发。
class ImageDataSource implements ICollectionData {
private imgList: string[]
constructor(list: string[]) {
this.imgList = list
}
getTotalCount(): number { return this.imgList.length }
getData(index: number): string { return this.imgList[index] }
setDataChangeListener(listener: DataChangeListener): void {}
}
@Entry
@Component
struct PhotoAlbum {
// 模拟相册数据
albumData: ImageDataSource = new ImageDataSource(
Array.from({ length: 80 }, (_, i) => `图片 ${i + 1}`)
)
build() {
Column() {
Text("我的相册")
.fontSize(24)
.fontWeight(FontWeight.Bold)
.padding(15)
Grid() {
LazyForEach(this.albumData, (name: string) => {
GridItem() {
Stack() {
Rect().width("100%").height(120).fill("#B0C4DE")
Text(name).fontColor(Color.White).fontSize(14)
}
.width("100%")
.borderRadius(6)
}
})
}
.columnsTemplate("1fr 1fr 1fr")
.columnGap(8)
.rowGap(8)
.layoutWeight(1)
}
.width("100%")
.height("100%")
.backgroundColor("#FFFFFF")
}
}
六、开发总结与性能优化
6.1 布局组件选用规则
- 单列滚动列表、聊天页、资讯页:优先使用
List; - 多列图标、相册、商品宫格:优先使用
Grid; - 分组展示内容:使用
ListItemGroup快速实现分组标题。
6.2 懒加载使用规范
- 数据量 超过 30 条 建议使用
LazyForEach,替代普通ForEach; - 图片类页面必须开启懒加载,避免一次性加载大量图片造成 OOM;
- 懒加载数据源必须实现
ICollectionData接口,保证数据驱动正常。
6.3 通用优化技巧
- 列表 / 网格项样式尽量简化,减少嵌套组件层级;
- 图片统一设置固定宽高,避免动态宽高引发布局抖动;
- 下拉刷新、上拉加载增加加载状态提示,提升交互体验。
七、拓展方向
- 实现瀑布流布局,打造图文资讯流页面;
- 结合路由跳转,实现点击列表 / 宫格项跳转到详情页;
- 学习列表侧滑删除、多选操作等高级交互。
更多推荐

所有评论(0)