UNPKG

@z-cloud/virtual-taro

Version:

一个基于React + TS开发的虚拟列表,支持瀑布流、grid的组件。

116 lines (115 loc) 3.71 kB
import { jsx } from "react/jsx-runtime"; import { useVirualizer, useIsomorphicLayoutEffect } from "../hooks/use-virtualizer.js"; import { Fragment } from "react"; import { ScrollView, View } from "@tarojs/components"; import { getWindowRect, getRectSizeAsync, getScrollViewContextNode, virtualizerUUID } from "../utils/index.js"; import Taro from "@tarojs/taro"; function GridVirtualList({ children, className, itemClassName, style, itemStyle, grid, gridSize, size, onReady, ...props }) { const scrollId = `zcloud-virtual-list-${virtualizerUUID.value++}`; const rowVirtualizer = useVirualizer({ ...props, size: (gridSize == null ? void 0 : gridSize[1]) ?? size, // 滚动模式只能竖向滚动 horizontal: false }); const colVirtualizer = useVirualizer({ ...props, size: (gridSize == null ? void 0 : gridSize[0]) ?? size, horizontal: true }); const rowTotalSize = rowVirtualizer.getTotalSize(); const colTotalSize = colVirtualizer.getTotalSize(); const onScroll = (e) => { rowVirtualizer.onScroll(e.detail); colVirtualizer.onScroll(e.detail); }; const init = async () => { const windowRect = getWindowRect(); const elementRect = await getRectSizeAsync(scrollId); const scrollNode = await getScrollViewContextNode(scrollId); rowVirtualizer.setScrollElementRect(props.followPageScroll ? windowRect : elementRect); rowVirtualizer.scrollTo = function(offset, behavior) { if (!scrollNode) { console.warn("获取scrollNode失败"); return; } scrollNode.scrollTo({ [this.options.horizontal ? "left" : "top"]: offset, animated: props.dynamicSize ? false : behavior === "smooth" }); }; if (props.followPageScroll) { rowVirtualizer.options.scrollMargin = elementRect.top ?? 0; rowVirtualizer.scrollTo = (offset, behavior) => { Taro.pageScrollTo({ scrollTop: offset, // 动态尺寸不支持滚动动画 duration: behavior === "smooth" && !props.dynamicSize ? 300 : 0 }); }; } colVirtualizer.setScrollElementRect(elementRect); colVirtualizer.scrollTo = rowVirtualizer.scrollTo ?? (() => { }); rowVirtualizer.init(); colVirtualizer.init(); if (rowVirtualizer && colVirtualizer) { onReady == null ? void 0 : onReady(rowVirtualizer, colVirtualizer); } }; useIsomorphicLayoutEffect(() => { init(); return () => { rowVirtualizer.clean(); colVirtualizer.clean(); }; }, [rowVirtualizer, colVirtualizer]); return /* @__PURE__ */ jsx( ScrollView, { scrollX: true, scrollY: true, enhanced: true, className, style: { overflow: "auto", ...style }, id: scrollId, onScroll, children: /* @__PURE__ */ jsx( View, { style: { height: rowTotalSize, width: colTotalSize, display: "grid", gridTemplateAreas: `"item"` }, children: rowVirtualizer.getVirtualItems().map((rowItem) => /* @__PURE__ */ jsx(Fragment, { children: colVirtualizer.getVirtualItems().map((colItem) => /* @__PURE__ */ jsx( View, { className: itemClassName, style: { ...itemStyle, gridArea: "item", height: rowItem.size, width: colItem.size, transform: `translate(${colItem.start}px,${rowItem.start}px)` }, children: children(rowItem, colItem) }, colItem.index )) }, rowItem.key)) } ) } ); } export { GridVirtualList };