在前端开发过程中(以React+Ant Design+虚拟滚动技术栈为例),开发者经常会遇到表格展示大量数据时的性能问题。虽然初始渲染或动态切换时出现的页面卡顿可以通过分页机制解决,但在某些必须展示全量数据的场景下,虚拟滚动技术就成为了必备方案。然而当表格需要支持表头筛选功能(包括搜索、枚举单选/多选、排序、自定义筛选等)时,传统的虚拟滚动方案往往无法满足需求。
1. 实现难点分析
现有技术方案的局限性
- 目前网络上关于虚拟滚动结合自定义筛选功能的实践案例相对匮乏。以Ant Design结合react-window的实现为例,这些案例大多仅展示基础的数据呈现功能。当需要实现复杂的表格筛选交互时,开发者往往面临较大挑战。即使对Ant Design Table API非常熟悉的开发人员,实现起来也相当繁琐。
2. 技术实现方案
基于React 17+Ant Design 4.22+ali-react-table 2.6的技术栈实现:
-
本方案通过Ant Design Table的基础架构,结合ali-react-table提供的组件和API,实现了虚拟滚动与筛选功能的完美结合:
- 基础配置兼容性:完全遵循Ant Design Table的columns和dataSource配置规范
- 核心筛选功能实现:重点实现了搜索功能,以下是关键代码(usePageCalc.tsx)实现:
import { SearchOutlined } from '@ant-design/icons'; import { Button, Input, Popconfirm } from 'antd'; import React, { useMemo, useState } from 'react'; const usePageCalc = () => { const inputRef = React.createRef(); const searchRef = React.createRef(); const [inputKeys, setInputKeys] = useState(['']); const [searchKeys, setSearchKeys] = useState(''); const columns = [ { title: ( <div className="ant-table-filter-column"> <span className="ant-table-column-title">名称</span> <span role="button" className="ant-dropdown-trigger ant-table-filter-trigger" style={{ margin: 0 }} onClick={() => setTimeout(() => inputRef.current!.select())} > <Popconfirm ref={searchRef} placement="bottomRight" overlayClassName="pop-overlay-ProvinceDepthPeakShaving" title={ <div style={{ padding: 8 }}> <Input ref={inputRef} placeholder={'搜索名称'} value={inputKeys[0]} onChange={(e) => setInputKeys(e.target.value ? [e.target.value] : [])} onPressEnter={() => { setSearchKeys(inputKeys[0]); // 关闭气泡弹窗 searchRef.current!.close(); }} style={{ width: 188, marginBottom: 8, display: 'block' }} /> <Button type="primary" onClick={() => { setSearchKeys(inputKeys[0]); // 关闭气泡弹窗 searchRef.current!.close(); }} icon={<SearchOutlined />} size="small" style={{ width: 90, marginRight: 8 }} > 搜索 </Button> <Button onClick={() => setInputKeys([''])} size="small" style={{ width: 90 }}> 重置 </Button> </div> } > <SearchOutlined style={{ color: '#bfbfbf' }} /> </Popconfirm> </span> </div> ), dataIndex: 'devName', fixed: 'left', width: 160, ellipsis: true, rowSpan: 8, }, ]; const dataSource = useMemo(() => { const typeSource = []; return typeSource.filter((fItem) => (fItem?.devName || '').includes(searchKeys)); }, [searchKeys]); return { columns, dataSource }; }; export default usePageCalc;气泡弹窗样式调整:
.pop-overlay { .ant-popover-arrow, .ant-popover-buttons, .ant-popover-message-icon { display: none; } .ant-popover-inner-content, .ant-popover-message { padding: 0; } }
方案总结
本方案的核心在于基于Ant Design Table进行适配改造,通过ali-react-table提供的BaseTable组件及其内置API实现虚拟滚动功能后,再扩展表头搜索功能。该库已内置排序功能实现,其他自定义筛选功能可参考上述搜索功能的实现逻辑。虚拟滚动组件的具体实现可参考ali-react-table官方文档进行实现,如果开发者有更优的实现方案,欢迎在评论区分享交流。