@z-cloud/virtual-taro
Version:
一个基于React + TS开发的虚拟列表,支持瀑布流、grid的组件。
135 lines (134 loc) • 4.97 kB
JavaScript
;
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const jsxRuntime = require("react/jsx-runtime");
const useVirtualizer = require("../hooks/use-virtualizer.cjs");
const components = require("@tarojs/components");
const index = require("../utils/index.cjs");
const Taro = require("@tarojs/taro");
const resizable = require("./resizable.cjs");
const react = require("react");
function NormalVirtualList({
children,
className,
itemClassName,
style,
itemStyle,
dynamicSize = false,
scrollViewProps,
onReady,
...props
}) {
const [scrollId] = react.useState(() => `zcloud-virtual-list-${index.virtualizerUUID.value++}`);
const virtualizer = useVirtualizer.useVirualizer(props);
const { lanes = 1, horizontal } = props;
const totalSize = virtualizer.getTotalSize();
let gridTemplateAreas = Array.from(
{ length: lanes },
(_, index2) => horizontal ? `"lane${index2}"` : `lane${index2}`
).join(" ");
if (!horizontal) {
gridTemplateAreas = `"${gridTemplateAreas}"`;
}
Taro.usePageScroll((e) => {
virtualizer.onScroll(e);
});
const onScroll = (e) => {
var _a;
virtualizer.onScroll(e.detail);
(_a = scrollViewProps == null ? void 0 : scrollViewProps.onScroll) == null ? void 0 : _a.call(scrollViewProps, e);
};
const init = async () => {
const windowRect = index.getWindowRect();
const elementRect = await index.getRectSizeAsync(scrollId);
const scrollNode = await index.getScrollViewContextNode(scrollId);
virtualizer.setScrollElementRect(props.followPageScroll ? windowRect : elementRect);
virtualizer.scrollTo = (offset, behavior) => {
if (!scrollNode) {
console.warn("获取scrollNode失败");
return;
}
scrollNode.scrollTo({
[props.horizontal ? "left" : "top"]: offset,
animated: dynamicSize ? false : behavior === "smooth"
});
};
if (props.followPageScroll) {
virtualizer.options.scrollMargin = elementRect.top ?? 0;
virtualizer.scrollTo = (offset, behavior) => {
Taro.pageScrollTo({
scrollTop: offset,
// 动态尺寸不支持滚动动画 小程序都不建议使用动画
duration: behavior === "smooth" && !dynamicSize ? 300 : 0
});
};
}
virtualizer.init();
onReady == null ? void 0 : onReady(virtualizer);
};
useVirtualizer.useIsomorphicLayoutEffect(() => {
init();
return () => virtualizer.clean();
}, [virtualizer]);
return /* @__PURE__ */ jsxRuntime.jsx(
components.ScrollView,
{
...scrollViewProps,
scrollX: horizontal,
scrollY: !horizontal,
enhanced: true,
className,
style: { overflow: "auto", ...style },
id: scrollId,
onScroll,
children: /* @__PURE__ */ jsxRuntime.jsx(
components.View,
{
style: {
display: "grid",
gridTemplateAreas,
gridTemplateColumns: `repeat(${horizontal ? 1 : lanes}, 1fr)`,
gridTemplateRows: `repeat(${horizontal ? lanes : 1}, 1fr)`,
alignItems: dynamicSize && !horizontal ? "start" : "stretch",
justifyItems: dynamicSize && horizontal ? "start" : "stretch",
columnGap: horizontal ? void 0 : props.gap,
rowGap: horizontal ? props.gap : void 0,
height: props.horizontal ? "100%" : totalSize,
width: props.horizontal ? totalSize : "100%"
},
children: virtualizer.getVirtualItems().map((virtualItem) => /* @__PURE__ */ jsxRuntime.jsxs(
components.View,
{
className: itemClassName,
"data-index": virtualItem.index,
style: {
...itemStyle,
gridArea: `lane${virtualItem.lane}`,
height: horizontal || dynamicSize ? void 0 : virtualItem.size,
width: !horizontal || dynamicSize ? void 0 : virtualItem.size,
transform: props.horizontal ? `translateX(${virtualItem.start}px)` : `translateY(${virtualItem.start - (props.followPageScroll ? virtualizer.options.scrollMargin ?? 0 : 0)}px)`
},
children: [
dynamicSize && /* @__PURE__ */ jsxRuntime.jsx(
resizable.Resizable,
{
emitWhenMounted: true,
listId: `${scrollId}-${virtualItem.index}`,
style: { width: "100%" },
onResize: (res) => virtualizer.onElementSizeChange(virtualItem.index, {
width: res.width,
height: res.height
}),
children: children(virtualItem)
}
),
!dynamicSize && children(virtualItem)
]
},
virtualItem.index
))
}
)
}
);
}
exports.NormalVirtualList = NormalVirtualList;