@pixui-dev/pixui-react-virtualwaterfall
Version:
pixui 高性能React虚拟瀑布流组件
687 lines (686 loc) • 20.4 kB
TypeScript
import { h, Component, JSX } from 'preact';
interface CSSProperties {
[key: string]: string | number | undefined;
}
/**
* 虚拟瀑布流列表组件的属性配置
* @interface VirtualWaterfallProps
*/
interface VirtualWaterfallProps {
/** =================== 通用属性 =================== */
/**
* 根元素id
* @type {string}
* @optional
*/
rootId?: string;
/**
* 根元素className
* @type {string}
* @optional
*/
rootClassName?: string;
/**
* 根元素style
* @type {CSSProperties}
* @optional
*/
rootStyle?: CSSProperties;
/** =================== 虚拟列表相关 =================== */
/**
* 内容区域style
* @type {CSSProperties}
* @optional
*/
contentStyle?: CSSProperties;
/**
* 输入数据列表
* @type {any[]}
*/
data: any[];
/**
* 单个项目宽度(像素)
* @type {number}
*/
itemWidth: number;
/**
* 容器高度(像素)
* @type {number}
*/
containerHeight: number;
/**
* 列数
* @type {number}
*/
columns: number;
/**
* 列间距,默认10px
* @type {number}
* @default 10
* @optional
*/
gap?: number;
/**
* 可视区域外预加载的尺寸大小,默认0
* @type {number}
* @default 0
* @optional
*/
overscan?: number;
/**
* 获取单个项目的高度
* @param {any} item - 数据项
* @param {number} index - 数据项索引
* @param {number} itemWidth - 项目宽度
* @returns {number} 项目高度
*/
getItemHeight: (item: any, index: number, itemWidth: number) => number;
/**
* 渲染单个项目元素
* @param {any} item - 数据项
* @param {number} index - 数据项索引
* @returns {Object} 包含元素和引用的对象
* @returns {JSX.Element} returns.element - 渲染的元素
* @returns {Object} [returns.refs] - 元素引用对象
*/
renderItem: (item: any, index: number) => {
element: JSX.Element;
refs?: {
[key: string]: any;
};
};
/** =================== 滚动效果相关 =================== */
/**
* 滚动相关配置
* @type {VirtualListScrollProps}
* @optional
*/
scrollProps?: VirtualListScrollProps;
/** =================== 曝光回调相关 =================== */
/**
* 项目曝光回调函数
* @param {any} item - 曝光的数据项
* @param {number} index - 曝光项目的索引
* @param {Object} refs - 元素引用对象列表
* @optional
* @description 当项目进入可视区域时触发
*/
onItemExpose?: (item: any, index: number, refs?: object) => void;
/**
* 项目隐藏回调函数
* @param {any} item - 隐藏的数据项
* @param {number} index - 隐藏项目的索引
* @param {Object} refs - 元素引用对象列表
* @optional
* @description 当项目离开可视区域时触发
*/
onItemHide?: (item: any, index: number, refs?: object) => void;
/** =================== 缓存管理相关 =================== */
/**
* 是否启用元素缓存复用
* @type {boolean}
* @default true
* @optional
*/
useCache?: boolean;
/**
* 更新已复用项目的元素内容
* @param {any} item - 数据项
* @param {Object} refs - 元素引用对象
* @optional
* @description 需配合 useCache 使用,需配合 renderItem 返回的 refs 使用
*/
updateItem?: (item: any, index: number, refs: {
[key: string]: any;
}) => void;
/**
* 获取项目类型,用于分类缓存
* @param {any} item - 数据项
* @returns {string} 项目类型
* @optional
*/
getItemType?: (item: any) => string;
/** =================== 下拉刷新相关 =================== */
/**
* 是否启用下拉刷新
* @type {boolean}
* @default true
* @optional
*/
hasPullDownRefresh?: () => boolean;
/**
* 下拉刷新阈值
* @type {number}
* @default 50
* @optional
*/
pullDownRefreshThreshold?: number;
/**
* 下拉回调
* @optional
*/
onPullDown?: (scrollTop: number) => void;
/**
* 下拉刷新回调
* @optional
*/
onPullDownRefresh?: () => void;
/**
* 下拉结束回调
* @optional
*/
onPullDownEnd?: () => void;
/**
* 下拉刷新渲染区域
* @type {JSX.Element | JSX.Element[]}
* @optional
*/
renderPullDownArea?: () => JSX.Element | JSX.Element[];
/** =================== 加载更多相关 =================== */
/**
* 触底阈值,默认 100
* @type {number}
* @default 100
* @optional
*/
loadMoreThreshold?: number;
/**
* 是否还有更多数据可加载
* @returns {boolean} 是否有更多数据
* @optional
*/
hasMore?: () => boolean;
/**
* 加载更多数据的回调
* @optional
*/
loadMore?: () => void;
/**
* 加载更多渲染区域
* @type {JSX.Element | JSX.Element[]}
* @optional
*/
renderLoadMoreArea?: () => JSX.Element | JSX.Element[];
}
/**
* 虚拟瀑布流列表组件状态
* @interface VirtualWaterfallState
*/
interface VirtualWaterfallState {
/**
* 容器宽度
* @type {number}
*/
containerWidth: number;
}
interface VirtualListScrollProps {
/**
* 滚动回弹类型, 具体表现为是否可以拖动超过内容大小值
* - elastic: 触顶触底会回弹
* - clamped: 触顶触底不回弹
* - 默认值:elastic
*/
movementType?: 'elastic' | 'clamped';
/**
* 滑动灵敏度
* - 值越大滑动越灵敏, 滑动距离会乘上滑动灵敏度
* - 默认值:1
*/
scrollSensitivity?: number;
/**
* 是否有惯性
* - true: 滑动后会有惯性滚动
* - false: 滑动后立即停止
* - 默认值:true
*/
inertia?: boolean;
/**
* 惯性函数版本
* - 1: 倾向于unity的惯性效果
* - 2: 倾向于ue的惯性效果
* - 默认值:2
*/
inertiaVersion?: number;
/**
* 惯性衰减率, 仅在inertiaVersion为1时生效
* - 取值范围:0(立即停止)到 1(无减速)
* - 默认值:0.135
*/
decelerationRate?: number;
/**
* 静态速度阻力, 仅在inertiaVersion为2时生效
* - 每秒速度的固定衰减值
* - 默认值:100
*/
staticVelocityDrag?: number;
/**
* 摩擦系数, 仅在inertiaVersion为2时生效
* - 每秒速度的动态衰减值, 当前速度*frictionCoefficient
* - 默认值:2.0
*/
frictionCoefficient?: number;
}
/**
* 虚拟瀑布流列表组件
* @class VirtualWaterfall
* @extends {Component<VirtualWaterfallProps, VirtualWaterfallState>}
* @description 高性能的虚拟瀑布流列表实现,支持大量数据的流畅滚动和元素复用
*/
declare class VirtualWaterfall extends Component<VirtualWaterfallProps, VirtualWaterfallState> {
static defaultProps: {
loadMoreThreshold: number;
pullDownRefreshThreshold: number;
gap: number;
overscan: number;
};
/** =================== DOM 引用 =================== */
/**
* 容器DOM引用
* @private
* @type {Ref<HTMLDivElement>}
*/
containerRef: import("preact").RefObject<HTMLDivElement>;
/**
* 内容DOM引用
* @private
* @type {Ref<HTMLDivElement>}
*/
contentRef: import("preact").RefObject<HTMLDivElement>;
/**
* 加载更多DOM引用
* @private
* @type {Ref<HTMLDivElement>}
*/
private loadMoreRef;
/** =================== 数据相关 =================== */
/**
* 数据
* @public
* @type {any[]}
*/
renderData: any[];
/** =================== 布局状态 =================== */
/**
* 各列的当前高度
* @private
* @type {number[]}
*/
private columnHeights;
/**
* 总内容高度
* @private
* @type {number}
*/
private totalHeight;
/**
* 缓存的所有项目布局信息
* @private
* @type {CachedItemLayout[]}
*/
private cachedLayouts;
/**
* 已计算布局的项目数量
* @private
* @type {number}
*/
private layoutedItemCount;
/** =================== 可视化状态 =================== */
/**
* 当前可见的瀑布流项目列表
* @private
* @type {WaterfallItem[]}
*/
private waterfallItems;
/**
* 索引到瀑布流项目的映射表
* @private
* @type {Map<number, WaterfallItem>}
*/
private waterfallItemsMap;
/**
* 上次可见项目的索引列表,用于对比变化
* @private
* @type {number[]}
*/
private lastVisibleIndices;
/**
* 当前滚动位置(不存储在state中避免触发重渲染)
* @private
* @type {number}
*/
private currentScrollTop;
/**
* 可视区域起始索引
* @private
* @type {number}
*/
private visibleStartIndex;
/**
* 可视区域结束索引
* @private
* @type {number}
*/
private visibleEndIndex;
/** =================== 下拉刷新相关 =================== */
/**
* 是否启用下拉刷新
* @private
* @type {() => boolean}
*/
private hasPullDownRefresh;
/**
* 下拉刷新状态
* @private
* @type {'idle' | 'pulling' | 'ready' | 'refreshing'}
*/
private pullDownRefreshState;
/**
* 下拉刷新距离
* @private
* @type {number}
*/
private pullDownRefreshDistance;
/**
* 下拉刷新的最小距离阈值
* @private
* @type {number}
*/
private pullDownRefreshThreshold;
/** =================== 加载更多相关 =================== */
/**
* 是否正在加载更多
* @private
* @type {boolean}
*/
private isLoadingMore;
/** =================== 缓存复用 =================== */
/**
* 按类型分组的回收元素缓存池
* @private
* @type {Map<string, WaterfallItem[]>}
*/
private recycledWaterfallItemsByType;
/**
* 生成唯一key的计数器
* @private
* @type {number}
*/
private keyIndex;
/**
* 构造函数
* @param {VirtualWaterfallProps} props - 组件属性
*/
constructor(props: VirtualWaterfallProps);
/** =================== 生命周期方法 =================== */
/**
* 组件挂载后的回调
* @description 计算布局和渲染可视区域
*/
componentDidMount(): void;
/**
* 组件卸载前的回调
* @description 清理缓存
*/
componentWillUnmount(): void;
/**
* 组件更新前的回调
* @param {VirtualWaterfallProps} nextProps - 新的属性
* @param {VirtualWaterfallState} nextState - 新的状态
* @param {any} nextContext - 新的上下文
* @description 检查数据变化并相应地更新布局
*/
componentWillUpdate(nextProps: Readonly<VirtualWaterfallProps>, nextState: Readonly<VirtualWaterfallState>, nextContext: any): void;
/**
* 组件更新后的回调
* @param {VirtualWaterfallProps} prevProps - 旧的属性
* @param {VirtualWaterfallState} prevState - 旧的状态
* @param {any} snapshot - 快照
* @description 检查属性变化并相应地更新布局
*/
componentDidUpdate(prevProps: Readonly<VirtualWaterfallProps>, prevState: Readonly<VirtualWaterfallState>, snapshot?: any): void;
/** =================== 外部可调用方法 =================== */
/**
* 重新初始化
* @description 重新初始化瀑布流组件,包括清理缓存、重新计算布局、重新计算可视区域、重新渲染组件
*/
reset(): void;
/**
* 获取当前滚动位置
* @returns {number} 当前滚动位置
*/
getScrollTop(): number;
/**
* 滚动到指定位置
* @param {number} scrollLeft - 滚动到距离左侧的位置
* @param {number} scrollTop - 滚动到距离上方的位置
*/
scrollTo(scrollLeft: number, scrollTop: number): void;
/**
* 获取指定索引的项目
* @param {number} index - 要获取的项目索引
* @returns {any} 项目数据
*/
getLayoutInfoByIndex(index: number): {
x: number;
y: number;
width: number;
height: number;
columnIndex: number;
index: number;
};
/**
* 获取可视区域项目索引的拷贝
* @returns {number[]}
*/
getVisibleIndices(): number[];
/**
* 获取总内容高度
* @returns {number}
*/
getContentHeight(): number;
/**
* 更新指定索引的项目
* @param {number} index - 要更新的项目索引
* @param {any} item - 新的项目数据
*/
updateItemByIndex(index: number, item: any): void;
/**
* 删除指定索引的项目
* @param {number} index - 要删除的项目索引
*/
removeItemByIndex(index: number): void;
/**
* 添加子数据
* @param {any[]} data - 要添加的数据
*/
addSubData(data: any[]): any[];
/**
* 在指定索引添加子数据
* @param {any[]} data - 要添加的数据
* @param {number} index - 要添加的数据索引
*
* */
addSubDataAtIndex(data: any[], index: number): void;
/**
* 从指定索引开始重新计算布局
* @param {number} index - 要重新计算布局的索引
*/
layoutItemsFromIndex(index: any): void;
/** =================== 事件处理方法 =================== */
/**
* 滚动事件处理函数
* @private
* @description 处理滚动事件,更新可视区域和触发加载更多
*/
private handleScroll;
/**
* 检查下拉刷新状态
* @param {number} scrollTop - 当前滚动位置
* @description 检查下拉刷新状态,并触发下拉刷新
*/
checkAndTriggerPullDownRefresh(scrollTop: number): void;
/**
* 检查并触发加载更多数据
* @private
* @param {number} scrollTop - 当前滚动位置
* @description 当滚动接近底部时触发加载更多回调
*/
private checkAndTriggerLoadMore;
/** =================== 缓存管理方法 =================== */
/**
* 重置所有缓存状态
* @private
* @description 清空所有缓存数据,重置组件状态
*/
private resetCache;
/**
* 获取项目类型(用于分类缓存)
* @private
* @param {any} item - 数据项
* @returns {string} 项目类型
* @description 如果用户提供了getItemType函数则使用,否则返回默认类型
*/
private getItemType;
/**
* 将项目回收到缓存池中
* @private
* @param {WaterfallItem} waterfallItem - 要回收的瀑布流项目
* @description 将不可见的项目回收到对应类型的缓存池中以供复用
*/
private recycleElement;
/**
* 计算指定范围内项目的布局信息
* @private
* @param {number} startIndex - 开始索引
* @param {number} targetCount - 目标数量,即需要计算的项目的数量
* @description 使用瀑布流算法计算每个项目的位置和尺寸
*/
private layoutItems;
/**
* 计算当前可视区域内的项目
* @private
* @returns {boolean} 可见项目是否发生变化
* @description 基于当前滚动位置计算需要渲染的项目列表
*/
private calculateVisibleItems;
/**
* 获取优化的搜索范围
* @private
* @param {number} columns - 列数
* @returns {Object} 搜索范围对象
* @returns {number} returns.searchStartIndex - 搜索开始索引
* @returns {number} returns.searchEndIndex - 搜索结束索引
* @description 基于上次可见范围优化搜索区域,提高性能
*/
private getOptimizedSearchRange;
/**
* 在指定范围内查找可见项目
* @private
* @param {number[]} visibleIndices - 可见项目索引数组
* @param {number} viewportTop - 视口顶部位置
* @param {number} viewportBottom - 视口底部位置
* @param {number} searchStartIndex - 搜索开始索引
* @param {number} searchEndIndex - 搜索结束索引
* @returns {Object} 可见范围对象
* @returns {number} returns.newVisibleStartIndex - 新的可见开始索引
* @returns {number} returns.newVisibleEndIndex - 新的可见结束索引
*/
private findVisibleItems;
/**
* 全范围搜索(备用方案)
* @private
* @param {number[]} visibleIndices - 可见项目索引数组
* @param {number} viewportTop - 视口顶部位置
* @param {number} viewportBottom - 视口底部位置
* @returns {Object} 可见范围对象
* @returns {number} returns.newVisibleStartIndex - 新的可见开始索引
* @returns {number} returns.newVisibleEndIndex - 新的可见结束索引
* @description 当优化搜索失败时的全范围搜索备用方案
*/
private fullRangeSearch;
/**
* 更新可见范围索引
* @private
* @param {number} newVisibleStartIndex - 新的可见开始索引
* @param {number} newVisibleEndIndex - 新的可见结束索引
* @description 更新内部维护的可见范围索引值
*/
private updateVisibleIndices;
/**
* 处理可见项目变化
* @private
* @param {number[]} visibleIndices - 当前可见项目索引列表
* @param {any[]} data - 数据列表
* @returns {boolean} 是否有变化
* @description 比较新旧可见项目列表,处理进入和离开的项目
*/
private handleVisibleItemsChange;
/**
* 处理离开可视区域的项目
* @private
* @param {number[]} exitingIndices - 离开的项目索引列表
* @description 根据缓存策略处理离开可视区域的项目
*/
private handleExitingItems;
/**
* 处理进入可视区域的项目
* @private
* @param {number[]} enteringIndices - 进入的项目索引列表
* @param {any[]} data - 数据列表
* @description 为进入可视区域的项目创建或复用渲染元素
*/
private handleEnteringItems;
/**
* 从缓存复用元素
* @private
* @param {WaterfallItem[]} cachedElements - 缓存的元素列表
* @param {any} item - 数据项
* @param {CachedItemLayout} layout - 布局信息
* @param {string} itemType - 项目类型
* @param {number} index - 项目索引
* @description 从缓存池中获取元素并更新其内容和位置
*/
private reuseElementFromCache;
/**
* 创建新元素
* @private
* @param {any} item - 数据项
* @param {CachedItemLayout} layout - 布局信息
* @param {string} itemType - 项目类型
* @param {number} index - 项目索引
* @description 为新进入可视区域的项目创建渲染元素
*/
private createNewElement;
/** =================== 下拉刷新事件处理方法 =================== */
/**
* 触发下拉刷新
* @private
*/
private triggerPullDownRefresh;
/**
* 重置下拉刷新状态
* @private
*/
private resetPullDownRefresh;
/**
* 完成下拉刷新(外部调用)
* @public
* @description 手动完成下拉刷新
*/
finishPullDownRefresh(): void;
/**
* 处理滚动相关配置
* @private
* @returns {VirtualListScrollProps} 滚动相关配置
*/
private handleScrollProps;
/** =================== 渲染方法 =================== */
/**
* 渲染组件
* @returns {JSX.Element} 渲染的JSX元素
* @description 渲染虚拟瀑布流列表的主要结构
*/
render(): h.JSX.Element;
}
export { VirtualWaterfall };
export type { VirtualWaterfallProps };