分页父类
介绍
分页父类把列表请求和状态处理封装好了。你只需要关心请求成功时怎么展示列表,加载、错误、空数据、上拉加载都由框架统一处理。
使用流程
- ViewModel 继承
BaseNetWorkListViewModel并实现requestListData()。 - 页面使用
BaseNetWorkListView包住列表内容。 - 列表容器用
RefreshLayout处理下拉刷新和上拉加载。
列表状态
BaseNetWorkListUiState 有四种状态:
LOADING:加载中SUCCESS:请求成功ERROR:请求失败EMPTY:空数据
BaseNetWorkListViewModel API
文件位置:core/base/src/main/ets/viewmodel/BaseNetWorkListViewModel.ets
说明:T 为列表项的数据类型,对应仓库返回的业务实体。例如商品列表时,T 就是 Goods。
属性
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
uiState | 当前列表请求状态 | BaseNetWorkListUiState | LOADING |
listData | 列表数据 | Array<T> | [] |
isLoading | 是否正在加载 | boolean | false |
isEnableSlideUp | 是否启用上滑加载 | boolean | true |
currentPage | 当前页码 | number | 1 |
pageSize | 每页数量 | number | 10 |
showErrorToast | 是否展示失败提示 | boolean | false |
方法
| 方法 | 说明 | 参数 | 返回值 |
|---|---|---|---|
requestListData() | 子类实现,返回分页请求 Promise | - | Promise<NetworkResponse<NetworkPageData<T>>> |
onRefresh() | 下拉刷新 | - | void |
onLoadMore() | 上拉加载更多 | - | void |
onRefreshDirection(direction) | 处理下拉或上拉 | direction: "pull" | "slideUp" | void |
retryRequest() | 失败重试 | - | void |
BaseNetWorkListView API
文件位置:core/ui/src/main/ets/component/network/BaseNetWorkListView.ets
参数
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
uiState | 当前列表请求状态 | BaseNetWorkListUiState | LOADING |
onRetry | 失败后的重试回调 | () => void | 空函数 |
loadingBuilder | 自定义加载视图 | CustomBuilder | 空 |
errorBuilder | 自定义错误视图 | CustomBuilder | 空 |
emptyBuilder | 自定义空数据视图 | CustomBuilder | 空 |
content | 成功状态内容 | CustomBuilder | 空 |
RefreshLayout API
文件位置:core/ui/src/main/ets/component/refresh/RefreshLayout.ets
参数
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
loading | 是否处于加载状态 | boolean | false |
isEnableSlideUp | 是否启用上滑加载 | boolean | true |
scroller | 列表/网格使用的 scroller | Scroller | new Scroller() |
onRefresh | 下拉或上拉回调 | (direction: "pull" | "slideUp") => void | 空函数 |
content | 刷新容器内容 | CustomBuilder | 必传 |
使用示例
下面示例基于项目里的网络列表示例,展示 ViewModel 和页面的标准写法。
ViewModel
ts
import { BaseNetWorkListViewModel } from "base";
import { GoodsRepository } from "data";
import { Goods, GoodsSearchRequest, NetworkPageData, NetworkResponse } from "model";
/**
* @file Network List Demo 示例页 ViewModel
*/
@ObservedV2
export default class NetworkListDemoViewModel extends BaseNetWorkListViewModel<Goods> {
/**
* 商品仓库
*/
private repository: GoodsRepository = new GoodsRepository();
/**
* 请求商品分页数据
* @returns {Promise<NetworkResponse<NetworkPageData<Goods>>>} 网络请求 Promise
*/
protected requestListData(): Promise<NetworkResponse<NetworkPageData<Goods>>> {
const request: GoodsSearchRequest = new GoodsSearchRequest();
request.page = this.currentPage;
request.size = this.pageSize;
return this.repository.getGoodsPage(request);
}
}页面
ts
import { IBestCard, IBestCell } from "ibestui";
import { P100 } from "designsystem";
import { Goods } from "model";
import { AppNavDestination, BaseNetWorkListView, RefreshLayout } from "ui";
import NetworkListDemoViewModel from "../viewmodel/NetworkListDemoViewModel";
/**
* @file Network List Demo 示例页视图
*/
@ComponentV2
export struct NetworkListDemoPage {
/**
* Network List Demo 示例页 ViewModel
*/
@Local
private vm: NetworkListDemoViewModel = new NetworkListDemoViewModel();
/**
* 列表滚动控制器
*/
private listScroller: Scroller = new Scroller();
/**
* 构建 Network List Demo 示例页
* @returns {void} 无返回值
*/
build() {
AppNavDestination({
title: $r("app.string.demo_base_network_list_title"),
viewModel: this.vm
}) {
BaseNetWorkListView({
uiState: this.vm.uiState,
onRetry: (): void => this.vm.retryRequest(),
content: (): void => this.NetworkListDemoContent()
});
}
}
/**
* 构建网络列表示例内容
* @returns {void} 无返回值
*/
@Builder
private NetworkListDemoContent() {
RefreshLayout({
scroller: this.listScroller,
loading: this.vm.isLoading,
isEnableSlideUp: this.vm.isEnableSlideUp,
onRefresh: (direction): void => this.vm.onRefreshDirection(direction)
}) {
List({ space: 12, scroller: this.listScroller }) {
ForEach(this.vm.listData, (item: Goods) => {
ListItem() {
this.NetworkListDemoItem(item);
}
}, (item: Goods) => `${item.id}`);
}
.padding($r("app.float.space_padding_medium"))
.width(P100)
.height(P100);
}
}
/**
* 渲染列表项
* @param {Goods} item - 列表项数据
* @returns {void} 无返回值
*/
@Builder
private NetworkListDemoItem(item: Goods) {
IBestCard({ shadowRadius: 0 }) {
IBestCell({
title: item.title,
label: item.subTitle ?? "",
isLink: false,
hasBorder: false,
leftContentWidth: P100
});
}
}
}注意事项
- 页面只关心成功状态如何渲染列表,加载、错误和空数据由 BaseNetWorkListView 处理。
- 刷新与加载更多统一通过 RefreshLayout 触发,ViewModel 只处理数据与状态。