基础父类
概述
Core 层的基础父类模块提供了一系列 ViewModel 基类,用于简化页面开发。这些基类封装了常见的生命周期管理、状态管理和网络请求逻辑。
模块组成
| 类名 | 职责 | 使用场景 |
|---|---|---|
| BaseViewModel | 基础 ViewModel | 所有 ViewModel 的基类,提供生命周期钩子 |
| BaseNetWorkViewModel | 网络请求 ViewModel | 单次网络请求的页面 |
| BaseNetWorkListViewModel | 列表网络请求 ViewModel | 列表数据加载和分页的页面 |
BaseViewModel
简介
BaseViewModel 是所有 ViewModel 的基类,提供了完整的生命周期钩子方法。
生命周期方法
typescript
@ObservedV2
export class BaseViewModel {
// 页面出现前(组件创建后、build 前)
aboutToAppear(): void {}
// 页面隐藏前
aboutToDisappear(): void {}
// 组件构建完成
onDidBuild(): void {}
// 组件即将回收
aboutToRecycle(): void {}
// 主题即将应用
onWillApplyTheme(theme: Theme): void {}
// 生命周期:销毁
aboutToBeDeleted(): void {}
// 页面显示完成 - 来自 NavDestination
onShown(reason: VisibilityChangeReason): void {}
// 页面隐藏完成 - 来自 NavDestination
onHidden(reason: VisibilityChangeReason): void {}
}使用示例
typescript
import { BaseViewModel } from "@core/base";
@ObservedV2
export class MyViewModel extends BaseViewModel {
@Trace count: number = 0;
// 重写生命周期方法
aboutToAppear(): void {
super.aboutToAppear();
console.log("页面即将出现");
// 初始化数据
this.loadData();
}
aboutToDisappear(): void {
super.aboutToDisappear();
console.log("页面即将隐藏");
// 清理资源
}
private loadData(): void {
// 加载数据逻辑
}
}BaseNetWorkViewModel
简介
BaseNetWorkViewModel 是网络请求 ViewModel 的基类,封装了网络请求的状态管理和错误处理逻辑。
核心特性
- 自动状态管理:自动管理加载、成功、错误状态
- 请求重试:提供重试机制
- 错误提示:可配置是否显示错误 Toast
- 生命周期集成:页面出现时自动发起请求
类定义
typescript
@ObservedV2
export abstract class BaseNetWorkViewModel<T> extends BaseViewModel {
// UI 状态
@Trace uiState: BaseNetWorkUiState = BaseNetWorkUiState.LOADING;
// 请求成功后的数据
@Trace data: T | null = null;
// 控制请求失败时是否显示 Toast 提示
protected showErrorToast: boolean = false;
// 子类必须实现此方法,返回网络请求 Promise
protected abstract requestRepository(): Promise<NetworkResult<T>>;
// 发起请求
executeRequest(): void;
// 重试请求
retryRequest(): void;
// 请求开始前回调
protected onRequestStart(): void;
// 请求成功回调
protected onRequestSuccess(data: T): void;
// 请求失败回调
protected onRequestError(): void;
}UI 状态
typescript
export enum BaseNetWorkUiState {
LOADING, // 加载中
SUCCESS, // 成功
ERROR // 错误
}使用示例
typescript
import { BaseNetWorkViewModel } from "@core/base";
import { NetworkResult } from "@core/network";
interface UserInfo {
id: string;
name: string;
email: string;
}
@ObservedV2
export class UserProfileViewModel extends BaseNetWorkViewModel<UserInfo> {
// 实现抽象方法,返回网络请求
protected requestRepository(): Promise<NetworkResult<UserInfo>> {
return this.userService.getUserInfo();
}
// 可选:重写请求成功回调
protected onRequestSuccess(data: UserInfo): void {
super.onRequestSuccess(data);
console.log("用户信息加载成功:", data);
}
// 可选:重写请求失败回调
protected onRequestError(): void {
super.onRequestError();
console.log("用户信息加载失败");
}
}在页面中使用
typescript
@Entry
@Component
export struct UserProfilePage {
@Local viewModel: UserProfileViewModel = new UserProfileViewModel();
build() {
Column() {
// 根据 UI 状态显示不同内容
if (this.viewModel.uiState === BaseNetWorkUiState.LOADING) {
LoadingIndicator();
} else if (this.viewModel.uiState === BaseNetWorkUiState.ERROR) {
ErrorView({
onRetry: () => this.viewModel.retryRequest()
});
} else if (this.viewModel.data) {
// 显示数据
Text(this.viewModel.data.name);
Text(this.viewModel.data.email);
}
}
}
}BaseNetWorkListViewModel
简介
BaseNetWorkListViewModel 是列表网络请求 ViewModel 的基类,封装了列表数据加载、分页、下拉刷新和上拉加载更多的逻辑。
核心特性
- 分页支持:自动管理分页逻辑
- 下拉刷新:支持下拉刷新
- 上拉加载更多:支持上拉加载更多
- 状态管理:自动管理加载、成功、错误、空数据状态
- 数据合并:自动合并分页数据
类定义
typescript
@ObservedV2
export abstract class BaseNetWorkListViewModel<T> extends BaseViewModel {
// UI 状态
@Trace uiState: BaseNetWorkUiState = BaseNetWorkUiState.LOADING;
// 列表数据
@Trace dataList: T[] = [];
// 当前页码
protected currentPage: number = 1;
// 每页数量
protected pageSize: number = 20;
// 是否还有更多数据
@Trace hasMore: boolean = true;
// 是否正在加载更多
@Trace isLoadingMore: boolean = false;
// 子类必须实现此方法,返回网络请求 Promise
protected abstract requestRepository(page: number, pageSize: number):
Promise<NetworkResult<PageData<T>>>;
// 加载数据
loadListData(): void;
// 刷新数据
refreshData(): void;
// 加载更多数据
loadMoreData(): void;
}使用示例
typescript
import { BaseNetWorkListViewModel } from "@core/base";
import { NetworkResult, PageData } from "@core/network";
interface Product {
id: string;
name: string;
price: number;
}
@ObservedV2
export class ProductListViewModel extends BaseNetWorkListViewModel<Product> {
// 实现抽象方法,返回网络请求
protected requestRepository(page: number, pageSize: number):
Promise<NetworkResult<PageData<Product>>> {
return this.productService.getProductList(page, pageSize);
}
// 可选:自定义每页数量
constructor() {
super();
this.pageSize = 10;
}
}在页面中使用
typescript
@Entry
@Component
export struct ProductListPage {
@Local viewModel: ProductListViewModel = new ProductListViewModel();
build() {
Column() {
// 根据 UI 状态显示不同内容
if (this.viewModel.uiState === BaseNetWorkUiState.LOADING) {
LoadingIndicator();
} else if (this.viewModel.uiState === BaseNetWorkUiState.ERROR) {
ErrorView({
onRetry: () => this.viewModel.loadData()
});
} else if (this.viewModel.dataList.length === 0) {
EmptyView();
} else {
// 显示列表
List() {
ForEach(this.viewModel.dataList, (item: Product) => {
ListItem() {
ProductItem({ product: item });
}
});
// 加载更多
if (this.viewModel.hasMore) {
ListItem() {
LoadingMore();
}
.onAppear(() => {
this.viewModel.loadMoreData();
});
}
}
.onRefresh(() => {
this.viewModel.refreshData();
});
}
}
}
}最佳实践
1. 选择合适的基类
- 简单页面:使用
BaseViewModel - 单次网络请求:使用
BaseNetWorkViewModel - 列表页面:使用
BaseNetWorkListViewModel
2. 重写生命周期方法
typescript
aboutToAppear(): void {
super.aboutToAppear();
// 自定义逻辑
}3. 错误处理
可以通过 showErrorToast 控制是否显示错误提示:
typescript
constructor() {
super();
this.showErrorToast = true; // 显示错误 Toast
}4. 自定义请求回调
可以重写请求回调方法来添加自定义逻辑:
typescript
protected onRequestSuccess(data: T): void {
super.onRequestSuccess(data);
// 自定义成功处理逻辑
}
protected onRequestError(): void {
super.onRequestError();
// 自定义错误处理逻辑
}注意事项
- 状态管理:使用
@ObservedV2和@Trace确保状态变化能触发 UI 更新 - 生命周期:合理使用生命周期方法,避免内存泄漏
- 请求时机:
BaseNetWorkViewModel会在aboutToAppear时自动发起请求 - 分页逻辑:
BaseNetWorkListViewModel自动管理分页,无需手动处理