先上效果图
如图 表格是可配置列的,且列是可自定义的,也就是说可以有无限列,同时由于需求限制无法做成分页,需要一次性加载全量数据,因此延展出了性能问题。
1.底部合计栏固定对齐,拖动表格的同时合计跟着一起滚动对齐
具体思路就是给表格一个固定视窗的高度,动态获取表格配置(获取每列宽度,给合计栏的每个span一个相同的宽度),css开启滚动并隐藏合计栏的滚动条,监听表格的滚动事件,当表格滚动时给合计栏一个相同的滚动
ps:注意这时候并未开启虚拟滚动,开启虚拟滚动后滚动的视窗和现在是不一样的
<nz-table
#productTable
class="statistics-table"
[nzData]="dataList"
[nzFrontPagination]="false"
[nzScroll]="{ x: '100vw',y: '500px' }"
[nzShowPagination]="false"
>
.
.
.
</nz-table>
<div class="fixed-footer" id="fixedFooter">
<span *ngFor="let item of summarySettings" class="footer-item" [ngStyle]="{width: item.width}">
{{item.summary}}
</span>
</div>
这是表格大概模版
定义出来后我们再去浏览器打开f12,拖动表格滚动条,找到当前在滚动的元素,那么我们可以在控制台输入这么一段代码,回车运行后控制台会打印当前正在滚动的元素
function findscroller(element){
element.onscroll=function () {
console.log(element)
}
Array.from(element.children).forEach(findscroller)
}
findscroller(document.body)
那么我们找到滚动的元素是类为“pie-table-horizontal-scroll”的div块元素,我们就可以监听到这个元素,然后驱动合计栏与它保持一致的滚动
document.getElementsByClassName('ant-table-body')[0].addEventListener('scroll', (e:any) => {
document.getElementById('fixedFooter')!.scrollLeft = e.target.scrollLeft
})
那我们的功能就基本实现了,还有种情况就是表格列配置填不满整张表格时(比如只配置了一列,两列),表格列会自适应,那么我们的配置宽度就不准确了,会造成合计栏偏差的情况,这种情况下我们需要去获取表格列宽
getThCurrWidth() {
setTimeout(() => {
let ths = document.getElementsByTagName('th')
for (let i = 0; i < ths.length; i++) {
this.pickedColumnSettings[i].nzWidth = ths[i].offsetWidth;
}
this.loadSummarySettings()
}, 200)
}
//根据表格配置获取宽度的函数
loadSummarySettings() {
this.summarySettings = []
interface info {
id:number,
fieldName: string,
summary:any,
width: string
}
this.pickedColumnSettings?.forEach(e => {
let temp:info = {
id:e.id,
fieldName: e.fieldPropertyName,
summary: '',
width: e.nzWidth + 'px'
}
if(e.fieldPropertyName === 'workHours'){
temp.summary = this.summaryObj.workHours
}else if(e.fieldPropertyName === 'amount'){
temp.summary = this.summaryObj.amount
}else if(e.fieldPropertyName === 'quantity'){
temp.summary = this.summaryObj.quantity
}else if(e.fieldPropertyName === 'qualifiedQuantity'){
temp.summary = this.summaryObj.qualifiedQuantity
}else if(e.fieldPropertyName === 'unqualifiedQuantity'){
temp.summary = this.summaryObj.unqualifiedQuantity
}else if(e.fieldPropertyName === 'productIndex'){
temp.summary = '合计'
}else{
temp.summary = '-'
}
this.summarySettings.push(temp)
});
}
那么到这里,已经实现了需求,可是测试过程中发现数据一旦变多,超过700条页面就会崩溃,table需要花巨大的性能去渲染数据,页面会卡死。那么我们给出的解决方法就是:虚拟滚动
2.虚拟滚动开启后解决横向滚动失效
开启虚拟滚动非常简单,根据ng-zoro提供的方法只要在表格的配置开启就行了,在原来的表格上稍加改动
<nz-table
#productTable
class="statistics-table"
[nzData]="dataList"
[nzFrontPagination]="false"
[nzScroll]="{ x: '100vw',y: '500px' }"
[nzVirtualForTrackBy]="trackByIndex"
[nzShowPagination]="false"
[nzVirtualItemSize]="20"
>
.
.
.
</nz-table>
出现了新问题,横向滚动没了,了解后知道是由于虚拟滚动的特性,使用了absolute,所以没有滚动,那么我们换种思路,既然thead和tbody滚动无法滚动,那我们让整张表格滚动
在外层包裹一个div,并且把表格宽度给一个很大的值
<div class="pie-table-horizontal-scroll">
<nz-table
#productTable
class="statistics-table"
[nzData]="dataList"
[nzFrontPagination]="false"
[nzScroll]="{ y: '500px' }"
[nzVirtualForTrackBy]="trackByIndex"
[nzShowPagination]="false"
[nzVirtualItemSize]="20"
>
.
.
.
</nz-table>
</div>
再根据具体样式做出调整
.pie-table-horizontal-scroll ::ng-deep .ant-spin-nested-loading{
width: 5000px;
}
.pie-table-horizontal-scroll{
overflow: auto;
}
.pie-table-horizontal-scroll ::ng-deep .nz-table-hide-scrollbar{
overflow: hidden !important; //表头不对齐fixed
}
.fixed-footer{
width: 100%;
scrollbar-width: none; /* firefox */
-ms-overflow-style: none; /* IE 10+ */
overflow-x: scroll;
white-space: nowrap;
}
.fixed-footer::-webkit-scrollbar{
display: none;
}
.footer-item{
display: inline-block;
color: rgba(0, 0, 0, 0.85);
font-weight: 500;
text-align: center;
background-color: rgb(246,248,250);
line-height: 61px;
height: 61px;
vertical-align:middle;
// border-left: 1px solid #f0f0f0;
// border-bottom: 1px solid #f0f0f0;
// border-right: 1px solid #f0f0f0;
}
搞定