Skip to content

基础父类

概述

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();
  // 自定义错误处理逻辑
}

注意事项

  1. 状态管理:使用 @ObservedV2@Trace 确保状态变化能触发 UI 更新
  2. 生命周期:合理使用生命周期方法,避免内存泄漏
  3. 请求时机BaseNetWorkViewModel 会在 aboutToAppear 时自动发起请求
  4. 分页逻辑BaseNetWorkListViewModel 自动管理分页,无需手动处理

下一步