构建分页列表容器组件 PagedList(下拉刷新 + 上拉加载 + 空状态集成) HarmonyOS 5.0.0 或以上
手动在每个页面实现这些逻辑不仅重复,而且易出错。分页列表组件,帮助你统一处理加载逻辑、刷新控制与错误状态,极大简化分页类页面的开发复杂度。与 ResultStatus + EmptyView 完美联动作为内部子组件;提供加载完全部后的 footer 插槽;提供 loading 插槽自定义;本篇构建了一个高复用、功能完整的。集成空状态与错误状态统一展示;支持插槽渲染每行 item。支持自动滚动到底加
·
✅ 背景说明
在企业级应用中,分页加载的列表场景非常普遍,如:
-
消息中心分页滚动;
-
评论列表;
-
搜索结果加载更多。
这些页面通常要处理:
-
首次加载 loading
-
无数据 empty
-
分页加载更多
-
下拉刷新
-
加载失败重试
手动在每个页面实现这些逻辑不仅重复,而且易出错。本篇我们将封装一个集成分页逻辑、下拉刷新、加载更多、状态展示的复用组件:PagedList。
🧱 一、组件目标功能
-
接收
fetchData(page)异步方法; -
支持下拉刷新;
-
支持上拉加载;
-
内部维护分页与状态;
-
集成空状态与错误状态统一展示;
-
支持插槽渲染每行 item。
📦 二、组件结构设计
@Component
struct PagedList<T> {
@Prop fetch: (page: number) => Promise<T[]> = async () => [];
@Prop pageSize: number = 20;
@Prop renderItem: (item: T) => void = () => {};
}
🧠 三、状态变量封装
@State private list: T[] = [];
@State private page: number = 1;
@State private status: 'loading' | 'success' | 'error' | 'empty' = 'loading';
@State private loadingMore: boolean = false;
🚀 四、加载与刷新逻辑实现
async aboutToAppear() {
this.load(true);
}
private async load(refresh = false) {
if (refresh) {
this.page = 1;
this.list = [];
this.status = 'loading';
} else {
this.loadingMore = true;
}
try {
const result = await this.fetch(this.page);
if (refresh && result.length === 0) {
this.status = 'empty';
} else {
this.status = 'success';
this.list = [...this.list, ...result];
this.page++;
}
} catch {
this.status = 'error';
} finally {
this.loadingMore = false;
}
}
📄 五、组件视图实现
build() {
Column({ space: 10 }) {
if (this.status === 'loading') {
Progress().type(ProgressType.Ring)
return;
}
if (this.status === 'error') {
ResultStatus({
status: 'error',
message: '加载失败,请重试',
onRetry: () => this.load(true)
})
return;
}
if (this.status === 'empty') {
EmptyView({ type: 'empty', message: '暂无内容' })
return;
}
List() {
ListItem() {
PullRefresh(() => this.load(true)) {
Column() {
ForEach(this.list, item => this.renderItem(item), item => JSON.stringify(item))
if (this.loadingMore) {
Text('加载中...').fontSize(12).margin({ top: 8 })
} else {
Button('加载更多').onClick(() => this.load(false))
}
}
}
}
}
}.padding(20)
}
🧪 六、父组件调用示例
@Component
struct UserList {
async fetchPage(page: number): Promise<string[]> {
await delay(500);
if (page > 3) return [];
return Array.from({ length: 10 }, (_, i) => `第${(page - 1) * 10 + i + 1}个用户`);
}
build() {
PagedList<string>({
fetch: this.fetchPage,
renderItem: (name) => Text(name).fontSize(14).padding(10)
})
}
}
⚠️ 七、常见问题与处理建议
| 问题 | 原因 | 建议 |
|---|---|---|
| 重复加载 | load() 并发调用 |
加入 loading 状态判断防抖 |
| 滚动位置丢失 | 页面切换后未缓存列表 | 搭配 keepAlive 保持状态 |
| 没有触底加载 | 未接入滚动触底事件 | 可扩展为 Scroll + onReachBottom |
🚀 八、拓展建议
-
支持自动滚动到底加载更多;
-
支持分页缓存与懒加载;
-
提供 loading 插槽自定义;
-
提供加载完全部后的 footer 插槽;
-
与 ResultStatus + EmptyView 完美联动作为内部子组件;
✅ 小结
本篇构建了一个高复用、功能完整的 PagedList 分页列表组件,帮助你统一处理加载逻辑、刷新控制与错误状态,极大简化分页类页面的开发复杂度。
下一篇将进入第7篇:
《构建页面级状态容器组件 PageWrapper(布局 + loading + error + slot)》
更多推荐



所有评论(0)