Ant Design中实现表格的滚动加载
表格是我们做企业信息中最常用的前端组件之一,最近的一个需求中,客户提出了这样的一个需求:
你们表格的分页太麻烦了,我就想打开就看到所有数据,不要说xxxx不支持,我们以前用的xxxx系统就是这样的。
需求分解
客户真的需要一打开就看到所有数据吗?
并不是。
为什么这么说呢?因为所有的数据一次查询几千条,后面也有可能上万条。客户就算多长2个眼睛,一眼也不可能看得完这么数据,就算看得完,显示器也显示不完,接电视也不行。
所以我猜测客户真正想要的是什么:不想分页。
于是找了那个所谓的xxx系统看了一眼,果然就是如此,不过就是把分页换成了滚动加载。
解决方案
识别到了用户真正的需求,后面就是解决问题了,查了一个Ant Design的API文档,很遗憾,原生并不支持这个功能,但客户又着急解决问题,所以先用了一种hack的方式。
简要的代码如下:
class xxxx extends Component {
constructor(props, context){
super(props, context);
this.state = {
isShowModal: false
};
this.scrollLoading = debounce(this.scrollLoading.bind(this), 100); //bind function once
}
componentDidMount(){
document.querySelector('.ant-table-body')
.addEventListener('scroll', this.scrollLoading);
}
componentWillUnmount() {
document.querySelector('.ant-table-body')
.removeEventListener('scroll', this.scrollLoading);
}
scrollLoading (e) {
const scrollTop = get(e, 'target.scrollTop', 0);
const clientHeight = get(e, 'target.clientHeight', 0);
const scrollHeight = get(e, 'target.scrollHeight', 0);
const pageNum = get(this.stores, 'state.pageConfig.current', 1);
const pageSize = get(this.stores, 'state.pageConfig.pageSize', 0);
const total = get(this.stores, 'state.tableData.total', 0);
if (!scrollLoading && (scrollTop + clientHeight >= scrollHeight - 100) && (pageNum * pageSize < total)) {
scrollLoading = true;
this.getList({
pageNum: pageNum + 1
}).then(() => {
scrollLoading = false;
});
}
}
render() {
// page code here
}
简要解释一下上述代码。
- 构造函数的时候使用
debounce
函数做一个防抖,提升性能。 - 在页面加载完成后,监听antd中
Table
组件的scroll
事件,并将滚动加载的函数注册到回调中。 - 页面滚动的时候触发
scrollLoading
函数,对当前页面的滚动状态做个计算,在计算发现用户快滚动到底部的时候,触发分页加载。 - 在页面销毁的时候取消监听,防止内存泄漏。
存在的问题
上面的代码可以解决客户的燃眉之急,但其实有不少问题。
- 页面存在多个表格会有冲突。
- 页面性能低下,数据量大的时候,滚动会有延迟。
- 后端接口速度不给力,还是能让用户感知到在加载行为。
下一步规划
针对上述问题,也有一些解决方案。
- 给每个表格手动传入一个id
- 加入虚拟滚动(在G3组件库的版本中已经添加)提高性能
- 与后端配合,提升加载速度
- G3组件库封装,原生支持分页和滚动加载两种模式。
更多的解决方案还请大家多多留言指教。