父组件
<Tabs
activeKey={activeItem}
onChange={handleChangeLog}
>
{tabMap.map((tabItem) => {
return (
<Tabs.TabPane tab={tabItem.label} key={tabItem.key}>
<Spin spinning={loading} indicator={antIcon}>
<div className='log-box'>
{socketMsg.length > 0 &&
socketMsg[0].status &&
socketMsg[0].status === "error" && (
<ul>
{socketMsg.map((item, index) => {
return <li key={index}>{item.message}</li>;
})}
</ul>
)}
{socketMsg.length > 0 && !socketMsg[0].status && (
<VirtualTable
columns={tableColumns}
dataSource={socketMsg}
scroll={{
y: 450,
x: "100vw",
}}
/>
)}
</div>
</Spin>
</Tabs.TabPane>
);
})}
</Tabs>
## antd表格虚拟滚动子组件
```javascript
import { Table } from "antd";
import classNames from "classnames";
import ResizeObserver from "rc-resize-observer";
import React, {
useEffect,
useRef,
useState,
} from "react";
import { VariableSizeGrid as Grid } from "react-window";
import "./VirtualTable.less";
const VirtualTable = (props, ref) => {
const gridRef = useRef();
useEffect(() => {
if (props.dataSource.length > 0) {
gridRef.current.scrollTo({ scrollTop: 0 });
}
}, [props.dataSource]);
const { columns, scroll } = props;
const [tableWidth, setTableWidth] = useState(0);
const widthColumnCount = columns.filter(({ width }) => !width).length;
const mergedColumns = columns.map((column) => {
if (column.width) {
return column;
}
return {
...column,
width: Math.floor(tableWidth / widthColumnCount),
};
});
const [connectObject] = useState(() => {
const obj = {};
Object.defineProperty(obj, "scrollLeft", {
get: () => {
if (gridRef.current) {
return gridRef.current?.state?.scrollLeft;
}
return null;
},
set: (scrollLeft) => {
if (gridRef.current) {
gridRef.current.scrollTo({
scrollLeft,
});
}
},
});
return obj;
});
const resetVirtualGrid = () => {
gridRef.current?.resetAfterIndices({
columnIndex: 0,
shouldForceUpdate: true,
});
};
useEffect(() => resetVirtualGrid, [tableWidth]);
const renderVirtualList = (rawData, { scrollbarSize, ref, onScroll }) => {
ref.current = connectObject;
const totalHeight = rawData.length * 32;
return (
<Grid
ref={gridRef}
className='virtual-grid'
columnCount={mergedColumns.length}
columnWidth={(index) => {
const { width } = mergedColumns[index];
return totalHeight > scroll.y && index === mergedColumns.length - 1
? width - scrollbarSize - 1
: width;
}}
height={scroll.y}
rowCount={rawData.length}
rowHeight={() => 32}
width={tableWidth}
onScroll={({ scrollLeft }) => {
onScroll({
scrollLeft,
});
}}
>
{({ columnIndex, rowIndex, style }) => (
<div
className={classNames("virtual-table-cell", {
"virtual-table-cell-last":
columnIndex === mergedColumns.length - 1,
})}
style={style}
>
<pre>{rawData[rowIndex][mergedColumns[columnIndex].dataIndex]}</pre>
{/* {rawData[rowIndex][mergedColumns[columnIndex].dataIndex]} */}
</div>
)}
</Grid>
);
};
return (
<ResizeObserver
onResize={({ width }) => {
setTableWidth(width);
}}
>
<Table
{...props}
className='virtual-table'
columns={mergedColumns}
pagination={false}
showHeader={false}
components={{
body: renderVirtualList,
}}
/>
</ResizeObserver>
);
};
export default VirtualTable;
不生效原因
刚开始是通过点击切换tab然后通过ref去虚拟列表子组件进行操作
// useImperativeHandle(ref, () => ({
// showTopContent() {
// console.log(gridRef, "gridRef");
// // console.log(gridRef.current, "gridRef");
// const element = document.querySelector(".virtual-table .virtual-grid");
// // console.log(element, "element");
// element.scrollTop = 0;
// element.scroll({ top: 0 });
// // const chidelement = document.querySelector(
// // ".virtual-table .virtual-grid"
// // );
// // console.log(chidelement.children[0], "chidelement");
// // chidelement.children[0].scrollIntoView(0, 0);
// },
// }));
这样操作一直不生效是因为数据没有加载完成,导致不生效
如果你的数据是异步加载的,你可能需要在数据加载完成后再执行滚动操作。你可以在数据加载的回调函数中调用 scrollTo 方法,或者在 useEffect 钩子中添加对数据的依赖。
如果你的设置没有生效,可能是因为在数据加载完成之前就已经执行了滚动操作。你可以尝试在数据加载完成后再执行滚动操作。这通常可以通过在 useEffect 钩子中添加对数据的依赖来实现。
例如,假设你的数据是存储在 socketMsg 中的,你可以这样修改 useEffect 钩子:
useEffect(() => {
if (socketMsg.length > 0) {
gridRef.current.scrollTo({ scrollTop: 0 });
}
}, [socketMsg]);
这样,每次 socketMsg 更新时,都会执行滚动操作,将滚动条设置为从顶部开始展示。
如果你的数据是异步加载的,你可能需要在数据加载完成后再执行滚动操作。你可以在数据加载的回调函数中调用 scrollTo 方法,或者在 useEffect 钩子中添加对数据的依赖。
如果你仍然遇到问题,你可能需要检查你的 react-window 版本,或者考虑使用其他方法来控制滚动条的位置,例如使用原生的 DOM API。
此文章为8月Day05学习笔记,内容来源于极客时间《重学前端》,强烈推荐该课程!