承接前两篇 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 通用优化技巧
- 列表 / 网格项样式尽量简化,减少嵌套组件层级;
- 图片统一设置固定宽高,避免动态宽高引发布局抖动;
- 下拉刷新、上拉加载增加加载状态提示,提升交互体验。
七、拓展方向
- 实现瀑布流布局,打造图文资讯流页面;
- 结合路由跳转,实现点击列表 / 宫格项跳转到详情页;
- 学习列表侧滑删除、多选操作等高级交互。