基于 Taro v2 的小程序通用列表组件设计及实现方案(1)

前言

在日常前端的开发过程中,可能往往会遇到需要完成列表业务的需求。鉴于不同列表业务的需求大致相同,基本可分为几种常见状态:列表请求 Loading、列表正常渲染、列表加载失败(网络错误、接口错误等)、上滑加载更多数据(没有更多数据、接口错误)、下拉刷新列表等。

1、状态整理

根据不同状态,整理出以下状态类型:

image-20210907190546276.png

有了以上状态的简单梳理,我们可以很简单的设计出以下组件结构。

2、组件结构
  • CommonList.interface.ts - 组件与管理者的相关接口声明
  • CommonListManager.ts - 核心状态管理者:负责状态切换的核心逻辑
  • CommonList.tsx - 组件:负责渲染视图界面
  • CommonList.scss - 样式:负责美化视图界面
3、代码设计
CommonList.interface - 接口相关声明
/**
 * CommonList.state 参数类型
 *
 * @export
 * @interface CommonListState
 */
export interface CommonListState {
    // 组件当前的状态
    status: CommonListStatusEnum;
    // 组件页脚当前的状态
    footerStatus: CommonListFooterStatusEnum
}
/**
 * CommonList.props 参数类型
 *
 * @export
 * @interface CommonListProps
 */
export interface CommonListProps {
    // 传递 Manager 并绑定回调函数,分发 render 不同界面(CommonListManager)
    listManager?: ICommonListManager
    // 重新加载(刷新)
    onReload?: () => void
}
/**
 * 列表状态枚举
 */
export enum CommonListStatusEnum {
    // 网络错误
    CommonListStatusNetworkBrokenEnum = 0,
    // 服务器错误
    CommonListStatusServerErrorEnum,
    // 加载中
    CommonListStatusLoadingEnum,
    // 空白数据
    CommonListStatusEmptyDataEnum,
    // 正常数据
    CommonListStatusNormalEnum
}

/**
 * 列表页脚状态枚举
 */
export enum CommonListFooterStatusEnum {
    // 没有更多数据
    CommonListFooterStatusRechedToFooterEndEnum,
    // 加载更多数据
    CommonListFooterStatusFooterLoadingEnum,
    // 正常状态(隐藏)
    CommonListFooterStatusHiddenEnum
}

/**
 * CommonListManager 接口
 */
export interface ICommonListManager {
    // 设置页面状态的 Setter
    setStatus(status: CommonListStatusEnum): void;
    // 设置页面状态改变时产生的回调,用于反馈给组件进行 render
    setPageStatusChangeCallback(callback: (status: CommonListStatusEnum) => void): void;
    // 更新页面状态的核心逻辑
    update(response: ICommonListResult)
    // 设置页脚状态改变时产生的回调,,用于反馈给组件进行 render
    setFooterStatusChangeCallback(cb: (status: CommonListFooterStatusEnum) => void);
    // 是否可以获取更多数据
    canFetchMore(): boolean;
    // 获取页面状态的 Getter
    getStatus(): CommonListStatusEnum
}

/**
 * ICommonListResult 接口
 * 声明接口返回的数据格式,此处可以根据自己的业务需求自定义
 */
export interface ICommonListResult {
    // 列表总数据量
    total: number;
    // 每页多少条数据
    pageSize: number;
    // 第几页
    page: number;
    // 当前返回的列表数据长度
    listCount: number;
CommonListManager - 核心状态管理者
import { CommonListFooterStatusEnum, CommonListStatusEnum, ICommonListResult, ICommonListManager } from "./CommonList.interface";

export class CommonListManager implements ICommonListManager {
    // 页面状态
    protected pageStatus: CommonListStatusEnum = CommonListStatusEnum.CommonListStatusLoadingEnum
    // 页脚状态
    protected footerStatus: CommonListFooterStatusEnum = CommonListFooterStatusEnum.CommonListFooterStatusHiddenEnum
    // 列表总数据量
    protected total: number;
    // 每页多少条数据
    protected pageSize: number;
    // 第几页数据
    protected page: number;
    // 页面状态改变回调
    protected pageStatusChangeCallback: (status: CommonListStatusEnum) => void
    // 页脚状态改变回调
    protected footerStatusChangeCallback: (status: CommonListFooterStatusEnum) => void

    /**
     * 设置页面状态
     * @param status 状态
     */
    setPageStatusChangeCallback(cb: (status: CommonListStatusEnum) => void) {
        this.pageStatusChangeCallback = cb
    }

    /**
    * 设置页脚状态
    * @param status 状态
    */
    setFooterStatusChangeCallback(cb: (status: CommonListFooterStatusEnum) => void) {
        this.footerStatusChangeCallback = cb
    }

    /**
     * 设置页面状态
     * @param status 页面状态
     */
    setStatus(status: CommonListStatusEnum): void {
        this.pageStatus = status
        // 如果传递了回调函数
        if (this.pageStatusChangeCallback) {
        	// 状态改变,产生回调
            this.pageStatusChangeCallback(this.pageStatus)
        }
    }
}

超出字数限制了,代码放不全,第二篇再放 doge