环境:
antdesign 版本号, 5.11
一、实现目标
使用 AntDesign 中 Table的 scrollTo 来设置滚动条的显示位置,达到自动滑动效果。
简单介绍 scrollTo 方法:
scrollTo 有三个参数 ({index:number,top:number,key:React.key}),
index: 表示行索引(从 0 开始计数)。
key: 表示行的唯一 key。
top: 表示滚动到指定位置的距离顶部的偏移量,具体的 px值。
二、实现步骤
1.定义表格实体,并绑定到Table 中
// 请求表格实例
const sporemeterRef: any = useRef();
<Table
ref={sporemeterRef}>
</Table>
2.获取对应元素的高度,并调用scrollTo 方法,实现滚动的效果
useEffect(() => {
// 是否回到顶部
let increasing = true;
// 防抖节流,避免重复开启滚动条方法
let isScrolling = isSelt;
// table 元素
const tableNode = sporemeterRef?.current;
// 全部内容的高度
const tableHeight =
tableNode?.nativeElement?.querySelector('.ant-table-tbody')
?.offsetHeight;
// 显示内容的高度
const tableHeights =
tableNode?.nativeElement?.querySelector(
'.ant-table-body'
)?.offsetHeight;
// 被卷去的高度
let tableScrollTop =
tableNode?.nativeElement?.querySelector(
'.ant-table-body'
)?.scrollTop;
let continueScrolling = false; // 控制滚动是否继续执行
// 开始滚动方法
const scrollTable = () => {
// 判断是否存在这个元素节点,并且是否开启 false为 是否鼠标悬浮或者聚焦,开启自己滚动
if (tableNode && continueScrolling) {
// isScrolling 设置为 关闭,避免重复
isScrolling = true;
if (increasing) {
tableScrollTop += 0.3;
// 使用 scrollTo 方法,来定义显示的高度
tableNode.scrollTo({ top: tableScrollTop });
// 当 tableScrollTop 的高度 大于等于全部内容的高度 减去 显示内容的高度时,为触底状态,回到顶部
if (tableScrollTop >= tableHeight-tableHeights) {
increasing = false;
}
} else {
tableScrollTop = 0;
tableNode.scrollTo({ top: 0 });
increasing = true;
}
// 在每一帧结束后再次触发滚动操作
requestAnimationFrame(() => {
// 再次开启 滚动
isScrolling = false;
scrollTable();
});
}
};
return () => {
continueScrolling = false;
};
}, );
3.实现 鼠标悬浮至 Table 盒子上时停止自动滑动
因为 Table 的方法中没有 监听鼠标的移入和移出的监听方法,所以需要再 Table 的外部给一个 div盒子来监听div 鼠标移动方法
以下提供完整的代码,带注释,注意请将AntDesign 的版本升至 5.11及以上
完整代码:
import { useState, useEffect, useRef } from 'react';
import { Table } from 'antd';
const RollTable = () => {
// 表格实例
const sporemeterRef: any = useRef();
// 表格是否被选中
const [isSelt, setIsSelt]: any = useState(false);
const handleTableMouseEnter = () => {
setIsSelt(true);
};
const handleTableMouseLeave = () => {
setIsSelt(false);
};
const dataSource = [
{
key: '1',
name: '丙辰中秋',
age: ',',
address: '欢饮达旦'
},
{
key: '2',
name: '大醉,作此篇',
age: ',',
address: '兼怀子由。'
},
{
key: '3',
name: '明月几时有',
age: '?',
address: '把酒问青天。'
},
{
key: '4',
name: '不知天上宫阙',
age: ',',
address: '今夕是何年。'
},
{
key: '5',
name: '我欲乘风归去',
age: ',',
address: '又恐琼楼玉宇'
},
{
key: '6',
name: '高处不胜寒',
age: '。',
address: '起舞弄清影'
},
{
key: '7',
name: '转朱阁,',
age: ',',
address: '低绮户'
},
{
key: '8',
name: '照无眠',
age: '。',
address: '不应有恨,'
},
{
key: '9',
name: '何事长向别时圆',
age: '?',
address: '人有悲欢离合'
},
{
key: '10',
name: '月有阴晴圆缺',
age: ',',
address: '此事古难全。'
},
{
key: '11',
name: '但愿人长久',
age: ',',
address: '千里共婵娟。'
}
];
const columns: any = [
{
title: '水调歌头,明月几时有',
dataIndex: 'name',
key: 'name',
align: 'center'
},
{
title: '[ 宋 ]',
dataIndex: 'age',
key: 'age',
width: 80,
align: 'center'
},
{
title: ' 苏轼',
dataIndex: 'address',
key: 'address',
align: 'center'
}
];
useEffect(() => {
// 是否回到顶部 ,true 按照当前的高度进行,false 从头开始
let increasing = true;
// 防抖节流,避免重复开启滚动条方法
let isScrolling = isSelt;
// table 元素
const tableNode = sporemeterRef?.current;
// 全部内容的高度
const tableHeight =
tableNode?.nativeElement?.querySelector('.ant-table-tbody')?.offsetHeight;
// 显示内容的高度
const tableHeights =tableNode?.nativeElement?.querySelector('.ant-table-body')?.offsetHeight;
// 被卷去的高度
let tableScrollTop =tableNode?.nativeElement?.querySelector('.ant-table-body')?.scrollTop;
let continueScrolling = !isSelt; // 控制滚动是否继续执行
const scrollTable = () => {
// 判断是否存在这个元素节点,并且是否开启 false为 是否鼠标悬浮或者聚焦,开启自己滚动
if (tableNode && continueScrolling) {
// isScrolling 设置为 关闭,避免重复
isScrolling = true;
if (increasing) {
tableScrollTop += 0.3;
tableNode.scrollTo({ top: tableScrollTop });
if (tableScrollTop >= tableHeight - tableHeights) {
increasing = false;
}
} else {
tableScrollTop = 0;
tableNode.scrollTo({ top: 0 });
increasing = true;
}
// 在每一帧结束后再次触发滚动操作
requestAnimationFrame(() => {
// 再次开启 滚动
isScrolling = false;
scrollTable();
});
}
};
if (!isSelt) {
scrollTable(); // 如果 isSelt 为 false,立即执行滚动
}
return () => {
continueScrolling = false;
};
}, [isSelt]);
return (
<div
className='table-box'
style={{ width: '500px' }}
onMouseEnter={handleTableMouseEnter}
onMouseLeave={handleTableMouseLeave}
>
<Table
columns={columns}
ref={sporemeterRef}
dataSource={dataSource}
scroll={{ y: 200 }}
></Table>
</div>
);
};
export default RollTable;
效果图: