最近工作比较忙好久没写文章了,有一丢丢不知道如何写起了,那就先说说我是为什么要开发本文的组件把。公司有一个定位系统,基本上来说一个定位单位一分钟或者更短就会有一个定位点,这样一天下来就会有很多定位点了,如果表格想要一下子放一天甚至三天的数据,那么数据量将会特别大(可能会到达5万条左右的数据),如果我们显示的列又比较多的话,那么表格的卡顿问题就会很明显了。我们公司web端选择的ui框架是 iview ,说实话 iview 的其他组件还行,不过表格的话在大量数据面前显得很疲软,反而我以前使用的 easyui 之类的老框架的表格性能和功能上都很好,毕竟它们已经经历了很多优化,表格这个组件的拓展性很大,想要在性能和功能上都做好十分的困难。
easyui 是个与时俱进的框架,有一次我点开它的官网发现它已经出了基于现在热门的 vue、react、angular 的ui组件。于是我这次选择去看看它基于vue的表格,于是我看到了这个组件附上连接 。我发现它通过分页延迟加载的方法解决了大数据量卡断的问题,这是我基本能够理解的,不过看完之后我有一些疑问,首先如果他只渲染了一部分数据,在滚动条滚动的时候再加载数据,那么为什么滚动条为什么一直是那么长。机智的我打开了开发者模式查看了表格部分的html代码
一看我明白了,图中的表格底部和表格顶部部分就是滚动条高度一直不变的原因,而中间部分更具滚动条的滚动始终只加载40条数据,这样大数据量的表格卡顿问题就解决了
2.思路确认
那么思路我们基本上可以有了,我们来理一下。
首先我们可以认为这个表格分为 3个部分 [表格顶部:( top )、表格滚动区域:( screen )、表格底部:( bottom )]。
top 和 bottom 部分的问题是高度的计算,基本上可以确定应该再滚动条滚动的时候,得到滚动的位置,然后更具总数据量和 screen 部分的数据量计算出 top 和 bottom 的高度,想到这里我脑海里就出现了几个字( 计算属性 )用在这里应该再合适不过了。
screen 部分的实现心中的初步想法是更具滚动高度计算应该加载的数据。不过如何做到在过度数据的时候更加流畅,心中还有一些些疑惑于是我继续观察了它的html。为了更好的表述,前端达芬奇打开了他的画图软件开始了作画(●'◡'●)
首先我们刚刚提到了screen部分始终显示40条数据,所以我们通过滚动事件判断当页面滚动到超过screenbottom部分的底部的时候我们就向下加载20条数据同时删除screentop部分的数据这样用户使用的时候不会出现向下滚动加载然后轻微上移又要加载的情况。看到这里很多人肯定在想如果这个用户是个皮皮怪,拉着滚动条疯狂拖动怎么办,那我们就再来看一张图片(●'◡'●)
如果皮皮怪们将滚动条滚到了大于本来待加载20条数据高度的位置,我们就用新的处理方式删除所有的40条数据,根据滚动的位置计算当前位置上下各20条的数据。再这个过程当中可能会出现表格变白一下的过程,不过我觉得应该可以通过遮罩层来处理。
基本上的思路有了,那么我们开始实现它吧 (●'◡'●)。
二、实现过程
(首先我先说一下,我实现的这个表格并不是考虑的那么全面,开发的初衷只是解决卡断这个问题,表格排序多选之类的功能等之后再拓展)
1.表格的结构
表格通过2个table标签组成,第一个是表头第二个是数据内容,方便后期拓展。这里偷懒没有把表头和内部内容和tr再单独成一个组件让代码可读性更好之后还可以再优化。
2.逻辑实现
我们直接说最主要的逻辑部分,首先我们看看props和data部分
props: { loadNum: { //默认加载行数 type: [Number, String], default() { return 20; } }, tdHeight: { //表格行高 type: [Number, String], default() { return 40; } }, tableHeight: { //表格高度 type: [Number, String], default() { return "200"; } }, tableList: { //所有表格数据 type: Array, default() { return []; } }, columns: { //所有表格匹配规则 type: Array, default() { return []; } }, showHeader: { type: Boolean, default: true } }, data() { return { isScroll: 17, showLoad: false, columnsBottom: [], //实际渲染表格规则 showTableList: [], //实际显示的表格数据 loadedNum: 0, //实际渲染的数据数量 dataTotal: 0, //总数据条数 dataTop: 0, //渲染数据顶部的高度 scrollTop: 0, //滚动上下的距离 interval: null, //判断滚动是否停止的定时器 scrollHeight: 0, //数据滚动的高度 selectTr: -1 //选择的行 }; },
然后我们看看滚动事件应该做一些什么先上代码