- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个 react-virtualised
InfiniteLoader
由单行组成。
我认为,主要问题是每个单元格的高度可能不同,并且必须为每个单元格加载不同的图像,因此高度不是静态的,并且会随着图像加载而变化。但即使当所有单元格的高度完全相同。
这是我当前使用 react-virtualised
InfiniteLoader
和 Grid
的组件
/* eslint-disable no-underscore-dangle */
import React, {
FC,
LegacyRef,
useEffect,
useLayoutEffect,
useMemo,
useRef
} from "react";
import {
InfiniteLoader,
Grid,
SectionRenderedParams,
AutoSizer,
WindowScroller,
GridCellProps,
ColumnSizer,
CellMeasurerCache,
CellMeasurer,
Index,
InfiniteLoaderChildProps,
WindowScrollerChildProps,
Size,
SizedColumnProps
} from "react-virtualized";
import { CellMeasurerChildProps } from "react-virtualized/dist/es/CellMeasurer";
import PuffLoader from "react-spinners/PuffLoader";
import useMeasure from "react-use-measure";
import { ResizeObserver } from "@juggle/resize-observer";
import styled from "styled-components";
const LOADER_SIZE = 100;
const LoaderWrapper = styled.div`
width: calc(100% - ${LOADER_SIZE}px);
text-align: center;
height: ${LOADER_SIZE}px;
margin: 15px 0px;
`;
interface InfiniteGridProps {
items: any[] | undefined;
defaultHeight?: number | undefined;
loadMoreItems?: () => Promise<void>;
totalResults?: number | undefined;
overscanRowCount?: number;
renderItem: (props: any, rowIndex: number) => React.ReactNode | undefined;
preventScrollLoader?: boolean;
}
interface GridParent {
_scrollingContainer?: any;
}
interface IGridCellProps extends GridCellProps {
parent: GridCellProps["parent"] & GridParent;
}
interface InfiniteGridItemProps {
renderItem: InfiniteGridProps["renderItem"];
gridItem: any;
reCalculateGrid: (
rowIndex: IGridCellProps["rowIndex"],
columnIndex: IGridCellProps["columnIndex"],
measure: CellMeasurerChildProps["measure"]
) => void;
rowIndex: IGridCellProps["rowIndex"];
columnIndex: IGridCellProps["columnIndex"];
parent: IGridCellProps["parent"];
measure: CellMeasurerChildProps["measure"];
}
const InfiniteGridItem: React.FC<InfiniteGridItemProps> = ({
renderItem,
gridItem,
reCalculateGrid,
rowIndex,
columnIndex,
parent,
measure
}) => {
const [rowRef, { height }] = useMeasure({ polyfill: ResizeObserver });
useLayoutEffect(() => {
reCalculateGrid(
rowIndex,
columnIndex,
parent._scrollingContainer ? measure : () => {}
);
}, [
height,
columnIndex,
measure,
parent._scrollingContainer,
reCalculateGrid,
rowIndex
]);
return <div ref={rowRef}>{renderItem(gridItem, rowIndex)}</div>;
};
const InfiniteGrid: FC<InfiniteGridProps> = ({
items,
defaultHeight = 300,
loadMoreItems,
totalResults,
overscanRowCount = 10,
renderItem
}) => {
const loaderRef = useRef<InfiniteLoader | undefined>();
const cache = useMemo(
() =>
new CellMeasurerCache({
fixedWidth: true,
defaultHeight
}),
[defaultHeight]
);
const onResize = () => {
cache.clearAll();
if (loaderRef && loaderRef.current) {
loaderRef.current.resetLoadMoreRowsCache(true);
}
};
const reCalculateGrid = (
rowIndex: IGridCellProps["rowIndex"],
columnIndex: IGridCellProps["columnIndex"],
measure: CellMeasurerChildProps["measure"]
) => {
cache.clear(rowIndex, columnIndex);
measure();
};
const isRowLoaded = ({ index }: Index) => {
if (items && totalResults !== undefined) {
const isLoaded = !!items[index] || totalResults <= items.length;
return isLoaded;
}
return false;
};
const loadMoreRows = async () => {
if (loadMoreItems) await loadMoreItems();
};
const cellRenderer = (
{ rowIndex, columnIndex, style, key, parent }: IGridCellProps,
columnCount: number
) => {
const index = rowIndex * columnCount + columnIndex;
const gridItem = items?.[index];
if (!gridItem || !renderItem) return null;
return (
<CellMeasurer
key={key}
cache={cache}
parent={parent}
columnIndex={columnIndex}
rowIndex={rowIndex}
>
{({ registerChild, measure }: any) => (
<div
ref={registerChild}
style={{
...style,
overflow: "visible"
}}
key={key}
>
<InfiniteGridItem
renderItem={renderItem}
gridItem={gridItem}
reCalculateGrid={reCalculateGrid}
rowIndex={rowIndex}
columnIndex={columnIndex}
parent={parent}
measure={measure}
/>
</div>
)}
</CellMeasurer>
);
};
useEffect(() => {
cache.clearAll();
if (loaderRef && loaderRef.current) {
loaderRef.current.resetLoadMoreRowsCache(true);
}
}, [loaderRef, cache, items]);
const infiniteLoaderRender = () => (
<WindowScroller>
{({
height,
onChildScroll,
scrollTop,
registerChild
}: WindowScrollerChildProps) => (
<div ref={registerChild}>
<InfiniteLoader
isRowLoaded={isRowLoaded}
loadMoreRows={loadMoreRows}
rowCount={totalResults}
threshold={1}
ref={loaderRef as LegacyRef<InfiniteLoader> | undefined}
>
{({ onRowsRendered }: InfiniteLoaderChildProps) => (
<AutoSizer disableHeight onResize={onResize}>
{({ width }: Size) => {
const columnCount = Math.max(Math.floor(width / width), 1);
return (
<ColumnSizer width={width} columnCount={columnCount}>
{({ registerChild: rg }: SizedColumnProps) =>
loaderRef && loaderRef.current ? (
<Grid
autoHeight
width={width}
height={height}
scrollTop={scrollTop}
ref={rg}
overscanRowCount={overscanRowCount}
scrollingResetTimeInterval={0}
onScroll={onChildScroll}
columnWidth={Math.floor(width / columnCount)}
columnCount={columnCount}
rowCount={Math.ceil(
(!items ? overscanRowCount : items?.length) /
columnCount
)}
rowHeight={cache.rowHeight}
cellRenderer={(gridCellProps: GridCellProps) =>
cellRenderer(gridCellProps, columnCount)
}
onSectionRendered={({
rowStartIndex,
rowStopIndex,
columnStartIndex,
columnStopIndex
}: SectionRenderedParams) => {
const startIndex =
rowStartIndex * columnCount + columnStartIndex;
const stopIndex =
rowStopIndex * columnCount + columnStopIndex;
return onRowsRendered({ startIndex, stopIndex });
}}
/>
) : null
}
</ColumnSizer>
);
}}
</AutoSizer>
)}
</InfiniteLoader>
</div>
)}
</WindowScroller>
);
const shouldRenderLoader =
!(items && items.length === totalResults) &&
loadMoreItems &&
items &&
items.length > 0;
const renderBottom = () => {
if (shouldRenderLoader)
return (
<LoaderWrapper>
<PuffLoader color={"#000"} size={LOADER_SIZE} />
</LoaderWrapper>
);
return null;
};
return (
<>
{infiniteLoaderRender()}
{renderBottom()}
</>
);
};
export default InfiniteGrid;
从this video可以看出,当您滚动到底部,然后尝试向上滚动时,它会剧烈移动。它应该只会向上移动几个像素,但比我预期的要多跳几个像素。
请注意 Test 752596
是如何靠近底部和滚动条的,我希望它在屏幕上稍微高一点,但在我不希望的时候似乎会出现整个其他项目它到。它大约在视频的 8 秒标记处,并且在那里似乎更加明显。
这是一个 CodeSandbox复制问题
有什么我可以做的让这更顺畅吗?
最佳答案
删除 <img src={image} alt="test" />
后我得到了改善.我在网络选项卡中看到,图像在上升时会重新加载。如果您查看 twitter 或 reddit 等无限滚动,上面的内容会部分卸载,但布局保持不变。这样它就不会弄乱文档高度。
也就是说,一旦你加载了图片,你应该将图片容器的大小设置为图片的大小,这样当图片被卸载时,布局在滚动位置上方保持不变。
小心放置height: 500px; max-height: 500px
,这不足以固定高度,如果列表元素上有填充或边距,这将影响列表本身。示例:在图像上填充 1000 像素,将使您的列表元素更大,即使您将列表元素的高度设置为 400 像素。纯粹在 CSS 中,这可以用 overflow: hidden
稍微修复一下。 ,但这一切可能会打乱计算。
margin有点类似,有个地方放margin: 50px auto
, 上面两个 div,div 的高度比你在 View 上看到的彩色矩形要大。
每次向下滚动时遇到颠簸,我都会看到“拍手”被记录下来。可疑。
useEffect(() => {
console.log("clap");
cache.clearAll();
if (loaderRef && loaderRef.current) {
loaderRef.current.resetLoadMoreRowsCache(true);
}
}, [loaderRef, cache, items]);
此外,对于任何使用 codesandbox 的人,请确保重新加载页面,而不仅仅是 iframe,否则您会收到如下错误:Children cannot be added or removed during a reorder operation.
.
当我向上滚动时,有时会被稍微推回到底部。也许正在加载向上滚动条并更改文档高度的内容?
另外你应该避免使用这种模式:
const infiniteLoaderRender = () => (<span/>)
return (
{infiniteLoaderRender()}
)
简化并避免不必要的重新渲染:
const infiniteLoaderRender = <span/>
return (
{infiniteLoaderRender}
)
这似乎确实大大改善了滚动。但不确定是否修复了它。
如果可以,不要用随机元素填充列表,而是制作一个固定列表版本,这样我们就可以轻松重现错误。
关于react-virtualized - InfiniteLoader 在loadMoreRows 完成后向上滚动时跳转,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72321400/
进程虚拟机和系统虚拟机有什么区别? 我的猜测是,进程 VM 没有为该操作系统的整个应用程序提供一种操作系统,而是为某些特定应用程序提供环境。 系统虚拟机为操作系统提供了一个安装环境,就像 Virtua
我在成员函数的上下文中理解 virtual,例如 virtual void frob()。但它在类声明的上下文中意味着什么,例如 class Foo : public virtual Bar? 对于给
根据 react-virtualized 文档,“AutoSizer 组件装饰 React 元素并自动管理宽度和高度属性,以便装饰元素填充可用空间”。 建议通常是加上height: 100%;或 fl
根据 this类似 StackOverflow 问题和其他文章,默认情况下 C# 方法是“非虚拟的”,我认为这意味着您不能在派生类中覆盖它们。 如果那是真的,能否请您向我解释一下,在下面的示例中,我如
我有一个基类Media和几个派生类,即DVD、Book等...基类写成: class Media{ private: int id; string title;
我搜索了一些关于虚函数声明的帖子,相信 =0 在 virtual void test()=0; 是固定句法所以 virtual void test()=NULL; virtual void test(
我正在使用 RV 列表加载具有自定义格式的大型文档。它非常有效,但我遇到了以下两个问题: 我目前在 cellmeasurer 中设置了一个列表 based on this计算行的动态高度(宽度是固定的
我一直在努力制作 this react virtualized table example工作 & 开始严重怀疑我的理智。我创建了一个 react 应用程序,我只是想在 App.js 中使用以下内容呈
我在Windows 7 Pro计算机上安装了Windows Virtual PC和Windows XP Mode。运行XP模式会在Virtual PC上自动安装XP。我想创建第二台与第一台相同的虚拟P
我使用 Virtual PC 来创建新的环境来测试我的安装程序。但我一定是做错了什么,因为内部装有 Vista 或 XP 的 VPC 镜像占用了大约 15GB 的磁盘空间(包括安装在其中的 VS200
是否可以为 Ubuntu 虚拟机动态分配处理器和内存?例如。进程在主机系统上运行,导致处理器的使用率从 30%-70% 上下波动,这些进程还占用 8GB 内存中 3GB-7GB 之间的波动量,即 1G
我正在使用“react-virtualized”来创建一个表。在该表中,一些数据可能显示为 'Brian Vaughn1'。 .此表格单元格应具有 font-weight: bold并且只应呈现文本,
我正在使用“react-virtualized”来创建一个表。在该表中,一些数据可能显示为 'Brian Vaughn1'。 .此表格单元格应具有 font-weight: bold并且只应呈现文本,
我一直在努力理解一段这样的代码: class A { // some class definition } class B { public: virtual A *s
基于 http://en.wikipedia.org/wiki/Virtual_inheritance class Animal { ... }; // Two classes virtually i
我看到 C++ 中的某些函数被声明为 virtual const int getNumber(); 但是如果函数声明如下有什么区别呢? const virtual int getNumber(); 这
问题来自C++ faq。 http://www.parashift.com/c++-faq-lite/protected-virtuals.html 使用公共(public)重载虚拟的代码: clas
这个问题在这里已经有了答案: How is "=default" different from "{}" for default constructor and destructor? (3 个答案
virtual final 函数(final 在基类)是否有任何 vtable/virtual 成本? class B{ public: virtual void fFinal() final
我有一个只包含 exe 文件(没有源代码)的 hello 工具。 你好工具结构: bin helloBin.exe helloRoot.exe conanfile.py conanfile.py
我是一名优秀的程序员,十分优秀!