
前端UI组件【免费下载链接】rsuite A suite of React components .项目地址https://gitcode.com/gh_mirrors/rs/rsuite点击查看免费下载导读当表格数据量从几百条增长到几千、上万条时一次性渲染全部行会导致 DOM 节点爆炸、滚动卡顿甚至页面崩溃。RSUITE 为Table提供了virtualized虚拟化渲染能力只渲染可视区域内的行从而以接近常量的渲染成本支撑大规模数据。本文以 RSUITE Table 虚拟化文档 为主体结合仓库内源码与示例完整讲解虚拟化表格的开启方式、底层原理、性能注意事项以及基于onScroll实现滚动到底部自动加载更多的无限滚动方案读完即可在真实项目中直接落地。一、为什么需要虚拟化大规模数据的渲染瓶颈RSUITE 官方文档对虚拟化表格的定位非常明确为大量数据提供虚拟化渲染支持以提高性能英文原文Provides virtualized rendering support for large amounts of data to improve performance见 docs/pages/components/table-virtualized/en-US/index.md。常规表格会把data中的每一行都渲染为一个真实 DOM 行节点。当数据量为数千行时浏览器需要同时维护数千个行元素滚动时的布局Layout与绘制Paint开销显著上升当数据量达到数万行时体验会急剧恶化。虚拟化的核心思想是无论数据总量多大始终只渲染视口viewport内可见的行以及上下少量缓冲行滚动时通过绝对定位与位移换算让新进入视口的行即时补位。从源码层面看RSUITE 的Table正是通过把virtualized属性透传给底层表格引擎来开启这一机制的详见后文源码分析一节。二、快速上手一行代码开启虚拟化开启虚拟化只需在Table上添加virtualized属性文档中给出的最小用法是Table virtualized /三、完整示例渲染 1000 行用户数据仅开启virtualized还不够直观官方文档在 虚拟滚动示例 中给出了一个渲染 1000 行用户数据的完整实例。示例先用mockUsers(1000)生成 1000 条用户数据该工具函数定义在 docs/utils/mock.ts内部使用 faker 生成id、firstName、lastName、gender、age、city、email等字段再通过Table.Column/Table.HeaderCell/Table.Cell声明各列import { Table } from rsuite; import { mockUsers } from ./mock; const { Column, HeaderCell, Cell } Table; const data mockUsers(1000); const App () { return ( Table virtualized height{400} data{data} Column width{70} aligncenter fixed HeaderCellId/HeaderCell Cell dataKeyid / /Column Column width{130} HeaderCellFirst Name/HeaderCell Cell dataKeyfirstName / /Column Column width{130} HeaderCellLast Name/HeaderCell Cell dataKeylastName / /Column Column width{100} HeaderCellGender/HeaderCell Cell dataKeygender / /Column Column width{100} HeaderCellAge/HeaderCell Cell dataKeyage / /Column Column width{200} HeaderCellCity/HeaderCell Cell dataKeycity / /Column Column width{200} HeaderCellEmail/HeaderCell Cell dataKeyemail / /Column /Table ); }; ReactDOM.render(App /, document.getElementById(root));这个示例值得注意的细节height{400}虚拟化依赖确定的视口高度来计算可见行范围必须显式指定heightTable 默认高度为 200见 Table Props 表。固定列与虚拟化共存首列Id同时设置了fixed与aligncenter说明开启虚拟化后依然可以正常使用固定列固定列会脱离普通行流悬浮于表格左侧。列声明方式不变虚拟化只影响行的渲染策略Column/HeaderCell/Cell的声明方式与普通表格完全一致。3.1 数据从哪来复用仓库的 mock 工具示例中的mockUsers来自仓库文档站的自定义 mock 工具 docs/utils/mock.ts。mockUsers(length)按给定长度生成用户数组每个用户包含id、name、firstName、lastName、avatar、city、street、postcode、email、phone、gender、age、stars、followers、rating、progress、amount、company、birthdate、joinDate等丰富字段非常适合做大规模表格的性能演示与压测数据源。你也可以直接复用它来验证自己项目中虚拟化表格的滚动表现。四、源码分析virtualized 属性是如何生效的要理解virtualized的实现路径可以从三个层面去看4.1 组件层属性透传RSUITE 的Table组件定义在 src/Table/Table.tsx。它是一个对底层表格库rsuite-table的再封装const CustomTable React.forwardRef(function Table(props, ref) { const { propsWithDefaults, rtl, getLocale } useCustom(Table, props); const { locale: overrideLocale, loadAnimation true, ...rest } propsWithDefaults; const locale getLocale(common, overrideLocale); return RsTable {...rest} rtl{rtl} ref{ref} locale{locale} loadAnimation{loadAnimation} /; });...rest会把包括virtualized、height、data、onScroll在内的所有表格属性原样传给rsuite-table的Table当前仓库在 package.json 中声明的依赖版本为rsuite-table: ^5.19.2。因此virtualized的最终渲染策略由rsuite-table引擎实现RSUITE 负责透传属性、统一 RTL 方向与多语言 locale。同时Table通过Object.assign挂载了五个子组件这就是示例中const { Column, HeaderCell, Cell } Table;解构的由来const Table Object.assign(CustomTable, { Cell: TableCell, Column: TableColumn, HeaderCell: TableHeaderCell, ColumnGroup: TableColumnGroup });4.2 样式层虚拟化行的定位方式在 src/Table/styles/index.scss 中可以看到表格行的布局模型——行是绝对定位的.rs-table-row { overflow: hidden; position: absolute; height: 36px; width: 100%; top: 0; .virtualized { include utils.pointer-event-none; } }这段代码印证了虚拟化的工作原理每一行都是一个绝对定位元素虚拟化引擎通过计算行的top偏移量把每一行钉在滚动容器内的正确位置上只有视口内的行才会被真正挂载到 DOM。而.virtualized类额外禁用了未渲染行的指针事件pointer-event-none避免幽灵行干扰鼠标交互。这种绝对定位 位移换算正是业界通行的 windowning 技术——RSUITE 仓库中 src/internals/Windowing/README.md 也说明Windowing技术大量借鉴了react-window的实现思路。4.3 关键前提固定行高虚拟化依赖固定的行高来精确计算可视行数与滚动位移。因此官方在 Table 文档 中给出了明确的兼容性警告⚠️ 我们不推荐将wordWrap和virtualized一起使用因为virtualized只有在固定行高的情况下才能达到最好的性能。你可以使用fullText属性来解决文本无法展示完整的问题。实践结论虚拟化表格应保持默认的固定行高rowHeight默认值为46见 Table Props 表。若行高可变例如通过rowHeight{rowData ...}按内容动态计算虚拟化的位移推算会失真可能出现行重叠或空白请谨慎使用。单元格文本被截断时优先使用Column的fullText属性鼠标悬停显示完整文本而不是开启wordWrap。五、进阶实战无限滚动加载更多数据虚拟化解决的是渲染性能但很多真实业务场景如日志列表、消息流、商品列表的数据是分页异步获取的。官方文档在 无限滚动加载示例 中展示了如何把虚拟化与滚动加载结合起来当用户滚动到表格底部附近时自动请求并追加下一页数据。5.1 完整示例import { Table, Loader, Box } from rsuite; const { Column, HeaderCell, Cell } Table; const FixedLoader () ( Loader contentLoading... style{{ display: flex, justifyContent: center, position: absolute, bottom: 0, background: var(--rs-body), width: 100%, padding: 4px 0 }} / ); const fetchData (start, length) { return Array.from({ length }).map((_, index) { return { index: start index, texts: faker.lorem.paragraph() }; }); }; const tableHeight 400; const App () { const [data, setData] React.useState(fetchData(0, 50)); const [loading, setLoading] React.useState(false); const loadMore () { setLoading(true); setTimeout(() { setData([...data, ...fetchData(data.length, 50)]); setLoading(false); }, 1000); }; const handleScroll (x, y) { const contextHeight data.length * 46; const top Math.abs(y); if (contextHeight - top - tableHeight 300) { loadMore(); } }; return ( Box posrelative Table virtualized shouldUpdateScroll{false} height{tableHeight} data{data} onScroll{handleScroll} Column width{100} HeaderCellIndex/HeaderCell Cell dataKeyindex / /Column Column width{200} flexGrow{1} HeaderCellTexts/HeaderCell Cell dataKeytexts / /Column /Table {loading FixedLoader /} /Box ); }; ReactDOM.render(App /, document.getElementById(root));5.2 逐段拆解实现要点1.onScroll回调与触底判定onScroll是表格滚动条滚动时的回调签名见 Table Props 表onScroll: (scrollX: object, scrollY: object) void示例中handleScroll的判定逻辑是const contextHeight data.length * 46; // 全部数据撑起的总内容高度默认行高 46 const top Math.abs(y); // 当前滚动距离取绝对值 if (contextHeight - top - tableHeight 300) { // 距底部不足 300px 时加载 loadMore(); }data.length * 4646 正是 Table 的默认行高rowHeight默认46与 Table Props 表 一致总内容高度 行数 × 行高当剩余未滚动距离contextHeight - top - tableHeight小于 300px 阈值时说明用户已接近底部触发loadMore()阈值300px可以按业务调整阈值越大越早预加载适合网络较慢的场景阈值过小则可能出现到底后空白等待。2.shouldUpdateScroll{false}防止滚动位置被重置shouldUpdateScroll的默认值是true其作用是决定 Table 尺寸更新后是否更新滚动。当新数据追加导致表格内容区高度变化时如果不加此属性表格滚动条可能会被重置到顶部用户正在浏览的位置就会丢失。示例中显式设置为false正是为了避免追加数据时滚动位置跳变该用法在 Table 展开行示例 中也有同样注释Prevent the scrollbar from scrolling to the top after the table content area height changes。类型上它既可以是boolean也可以是(event) ({ x, y })函数用返回值精确控制是否更新滚动位置。3. 加载状态的展示数据追加使用setTimeout模拟 1 秒网络延迟加载期间loading为true通过{loading FixedLoader /}在表格底部渲染一个绝对定位的Loader来自 RSUITE 的加载指示组件背景色使用 CSS 变量var(--rs-body)保证与当前主题一致外层使用Box posrelative让Loader可以相对表格容器做绝对定位钉在底部居中显示 Loading...。4.flexGrow弹性列第二列设置flexGrow{1}让该列自动吸收 Table 剩余宽度填满容器。注意flexGrow与width、resizable互斥不能同时设置可配合minWidth设定最小宽度详见 Table.Column Props 表。六、相关 Props 速查表以下是与虚拟化表格强相关的核心属性完整定义见 Table Props 表属性类型默认值说明virtualizedboolean开启虚拟化渲染高效渲染大表格数据heightnumber200表格高度虚拟化依赖确定视口高度data *object[]表格数据必填rowHeight(rowData) number \| number46行高虚拟化场景建议保持固定值onScroll(scrollX, scrollY) void滚动回调无限加载的判定入口shouldUpdateScrollboolean \| (event)({x,y})true表格尺寸更新后是否更新滚动追加数据时建议设为falseautoHeightboolean高度随数据行数自动扩展无纵向滚动条与虚拟化场景通常不搭配loadingboolean显示加载状态可配合renderLoading自定义renderEmpty(info: ReactNode) ReactNode自定义空数据展示七、进一步探索本专题还提供了官方中文版文档 docs/pages/components/table-virtualized/zh-CN/index.md两者内容一致可对照阅读。想深入了解虚拟化之外的能力官方 Table 文档 docs/pages/components/table/en-US/index.md 覆盖了排序、分页、可伸缩列、可展开行、树形表格、粘性表头等完整特性文档页面对应的渲染组件定义在 docs/pages/components/table-virtualized/index.tsx其中包含示例所需的Box、Loader、faker、mockUsers等依赖注入可作为在 CodeSandbox 中运行示例的参考。此外仓库还提供了 Sticky Table、Tree Table、Editable Table、Filterable Table 等专题可组合出完整的表格解决方案。赞分享前端UI组件【免费下载链接】rsuite A suite of React components .项目地址https://gitcode.com/gh_mirrors/rs/rsuite点击查看免费下载相关推荐rsuite Table 虚拟滚动virtualized实战轻松渲染万级数据行rsuite Table 虚拟滚动virtualized实战轻松渲染万级数据行 导读 本文以 rsuite 官方文档中的 Table 虚拟滚动示例为核心前端UI组件rsuite 虚拟滚动表格Table virtualized完整实战指南海量数据渲染与无限滚动加载rsuite 虚拟滚动表格Table virtualized完整实战指南海量数据渲染与无限滚动加载 导读 本文聚焦 rsuite 组件库中 Table前端UI组件React算法优化虚拟列表与无限滚动实战指南React算法优化虚拟列表与无限滚动实战指南 引言大数据渲染的性能挑战 在现代Web应用中处理大量数据渲染是一个常见的性能瓶颈。当用户需要浏览成千上万条数前端教程文档上一篇gogcli gog tasks undo 命令详解将已完成的 Google Tasks 任务恢复为待办状态下一篇Apache Maven Artifact Resolver ProviderMaven 仓库系统与 POM 解析的 Resolver 扩展层深度解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考