将每个th 设置为position:sticky;top:0;即可完成表头固定操作。注意设置z-index
兼容性,chrome> 90 (根据 caniuse:sticky)
<div style="overflow:auto;">
<table style="width:100%">
<thead>
<tr>
<th style="position:sticky;top:0;">th>
tr>
thead>
<tbody>
<tr>
<td style="position:sticky;left:0">td>
tr>
tbody>
table>
div>
使用background-image: linear-gradient,渐变1px,绘制border,防止border影响布局。(大量使用linear-gradient性能影响有待考究)
vxe-table也采用类似的方式:使用linear-gradient绘制纯色背景,但vxe-table 使用background-size 控制背景为1px;
计算总高度。使用width:1px;height:总高度;position:absolute; div元素。以此撑开容器,得到滚动条。
使用 可视区上距离 + 可视区下距离+ 可视区高度 计算出总高度。
可以用padding, margin, position:relative, transform:translate
这里使用两个
min-height控制可视区顶部距离和底部距离。在新版浏览器中,渲染不阻塞滚动条运动。若滚动过快,会导致表头消失。(因为整个table都在不可见区,此时sticky就不生效)
<div style="overflow:auto;">
<table style="width:100%">
<thead>
<tr>
<th style="position:sticky;top:0;">th>
tr>
thead>
<tbody>
<tr style="min-height:0px"><tr>
<tr>
<td style="position:sticky;left:0">td>
tr>
<tr style="min-height:100px"><tr>
tbody>
table>
div>
虚拟滚动时,表格中不要因为换行导致行高变化。
endIndex 要+1,防止特殊滚动时,表格最下方空白。
endIndex 大于数据总量时的特殊处理。
计算每一个列配置中的width/min-width/max-width。为确保计算的宽度不变,这里列配置中min-width === max-width。(后期使min-width = width?)
同y轴虚拟滚动方案。
这里用
<div style="overflow:auto;">
<table style="width:100%">
<thead>
<tr>
<th style="min-width:0px;">th>
<th style="position:sticky;top:0;">th>
<th style="min-width:100px;">th>
tr>
thead>
<tbody>
<tr style="min-height:0px"><tr>
<tr>
<td>td>
<td style="position:sticky;left:0">td>
tr>
<tr style="min-height:100px"><tr>
tbody>
table>
div>
在84版本,当横向滚动距离超过父元素宽度时,会导致sticky失效。
横向虚拟滚动在高版本浏览器中会有问题。也是滚动条不阻塞渲染导致,固定列跳动。
在84版本(高版本未尝试),横向滚动条移动到最右侧时,减少列数量,导致横向滚动条长度不重置。(猜测浏览器不重排transform图层)此时变动一下表格样式即可触发重排。
注意设置z-index 左上角表头最大。其次为表头和固定列,其次为表体。
虚拟滚动裁剪数组中,在startIndex前的固定列都需要保留。
计算虚拟滚动可视区左侧偏移量也需要调整
通过横向滚动scrollLeft 计算startIndex的算法也需要调整
原生 draggable="true" 实现
Object.freeze()
高亮行/单元格,渐暗。非虚拟滚动时,只要加上css @keyframe 关键帧动画,配合setTimeout 动画结束后移除class即可。
虚拟滚动由于元素会增加和移除。在滚动时,会导致可视区外的元素动画效果有问题。
在虚拟滚动时,需要手动计算行的背景。使用d3.interpolate 库来计算颜色过渡。通过window.requestAnimation 循环更新每一行的颜色。