@z-cloud/virtual-taro
Version:
一个基于React + TS开发的虚拟列表,支持瀑布流、grid的组件。
116 lines (115 loc) • 3.71 kB
JavaScript
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
};