实现效果如下:
功能点:
1. 当表格内容超出时,自动滚动,滚动到最后一条之后在从头滚动。
2. 表格中的数据会定时刷新,刷新后数据更新。
3. 鼠标移入表格中,停止滚动;移出后,继续滚动。
4. 点击表格中的排序功能,拉取后端数据,从头滚动。
先说一说实现过程中遇到的大坑吧
坑1: vue-seamless-scroll依赖的使用
1. 安装并对应引入
yarn add vue-seamless-scroll
局部引入:
import vueSeamlessScroll from "vue-seamless-scroll";
components: { vueSeamlessScroll },
2. 使用
用该组件包住要滚动的表格,并将表格数据传进去
参数:tableData是我的表格数据数组,defineScroll是滚动的参数,参考如下:
代码:
classOption() {
return {
step: 0.5, // 数值越大速度滚动越快
limitMoveNum: 5, // 开始无缝滚动的数据量
hoverStop: true, // 是否开启鼠标悬停stop
direction: 1, // 0向下 1向上 2向左 3向右
openWatch: true, // 开启数据实时监控刷新dom
singleHeight: 0, // 单步运动停止的高度(默认值0是无缝不停止的滚动) direction => 0/1
singleWidth: 0, // 单步运动停止的宽度(默认值0是无缝不停止的滚动) direction => 2/3
waitTime: 500, // 单步运动停止的时间(默认值1000ms)
};
},
3. 实际效果:
表头也会跟着滚动,要想表头不滚动很简单,利用两个表格组件,
a. 需要滚动的表格去掉表头,用vueSeamlessScroll 组件包着,
b. 将另一个表格放在vueSeamlessScroll 组件外边,只显示表格标题。
除此之外这个组件有个缺陷:数据更新的时候,dom却不会更新。
如上图,当数据量从17变为15时,滚动的dom的高度依旧是17的高度。为了解决这个问题,可以利用v-if的强制刷新。在数据有更新时先将updateFlag设为false,过100毫秒再设为true。
如此,基本上能保证正常显示所有的数据。但强制刷新会使得滚动进度刷新,从头开始滚。
看似很完美,但是坑在业务场景了,我们这边的数据刷新频率在10秒左右,也就意味着在我们的业务场景中只会看到前几条数据,因为每次数据更新,都会从头滚动。
基于此我放弃了该依赖的使用。
坑2: 使用scrollTop属性,找不到表格的bodyWrapper
看了好多文章,都说直接取用this.$refs.myTable.bodyWrapper,搁我这就直接报错,就找不着这个bodyWrapper。
实际实现步骤
主要实现逻辑使用的是操作表格体的滚动条,也就是坑2中找不到的bodyWrapper。
1. 找到要操作的dom节点
具体操作如上图,找到表格体的外层dom节点,有滚动条属性。然后点击右键将该节点显示在控制台上,修改该节点的scrollTop值,发现表格内容上移了,说明我们找对了节点。
接下来就是在代码中找到该节点,给表格加一个ref="tableData",然后你可以打印一下this.$refs.tableData,手动找一下刚刚在控制台操作的那个元素,我的是this.$refs.tableData.$refs.bodyWrapperScrollbar.$refs.wrap,然后操作一下该元素的scrollTop属性,看是否能操作表格的滚动条,这里有一个坑:直接操作可能不会生效,需要一个定时器改动。
2. 控制该节点的scrollTop属性
整体代码如下:
封装了方法之后,在created或mounted调用该方法即可。
其中定时器中(1000 / 60) * 3是定时执行的时间,控制滚动的快慢,可以自定义时间。
除此之外还有个需求就是:鼠标移入表格区,暂停移动,鼠标移出表格区继续移动。
封装一个停止移动的方法,同时给表格增加方法:鼠标移入停止移动,出来之后继续移动。
除此之外,还有一个需求是:手动点击某一列的排序时,需要从头滚动,则需要一个参数scrollInitFlag,用来判断是否从头滚动,初始值为true,在排序方法中将该值设置为true,同时在autoScrollFn方法中增加逻辑,如下图:
完整代码如下:
// 表格自动滚动
autoScrollFn() {
clearInterval(this.scrollTimer);
this.$nextTick(() => {
const tBody =
this.$refs.tableData.$refs.bodyWrapperScrollbar.$refs.wrap;
// 当可视窗口高度大于表格高度时,不滚动
if (tBody.clientHeight > tBody.scrollHeight) {
return;
}
if (this.scrollInitFlag) {
tBody.scrollTop = 0;
this.scrollInitFlag = false;
}
this.scrollTimer = setInterval(() => {
tBody.scrollTop += 1; // 每次上滑一个像素
// 当滚动到最底部(可视高度+距离顶部=整个高度)时,从头开始滚
if (tBody.clientHeight + tBody.scrollTop === tBody.scrollHeight) {
tBody.scrollTop = 0;
}
}, (1000 / 60) * 3); // 1000 / 60
});
},
stopScrollFn() {
clearInterval(this.scrollTimer);
this.scrollTimer = null;
},
// 排序
sortChangeFn({ column, prop, order }) {
console.log(column, prop, order);
// 调用后端接口
this.getDataFn();
this.scrollInitFlag = true;
},
基本上完了,做完之后我发现文字滚动的时候会抖动,暂时还没有啥好的想法,还有页面缩放之后滚动也不生效了,后面再解决吧。
从实际应用来看,若是没有我这么频繁的数据刷新,还是用vue-seamless-scroll依赖吧