开源 UI 库中,唯一同时实现了大表格虚拟化和树表格的 Table 组件 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
simonguo
V2EX    前端开发

开源 UI 库中,唯一同时实现了大表格虚拟化和树表格的 Table 组件

  •  
  •   simonguo 2019 年 1 月 18 日 2930 次点击
    这是一个创建于 2549 天前的主题,其中的信息可能已经有所发展或是发生改变。

    背景

    有这样一个需求,一位 React Suite (以下简称 rsuite)的用户,他需要一个 Table 组件能够像 Jira Portfolio 一样,支持树形数据,同时需要支持大数据渲染。 截止到目前( 2019 年 1 月 17 日)为止,开源 UI 库中没有找到可以支持的组件,所以 rsuite 在最新的版本中支持这一特性。

    接下来,我们看一下 rsuite 中是怎么支持这两个功能?

    大表格虚拟化

    首先,我们看一下支持大数据渲染,在页面中渲染过多的 DOM 元素会带来性能问题,必须得有一种解决方案去优化它,我们暂且叫做大表格虚拟化。

    所谓的大表格虚拟化,其实就是为表格设置一个较大的数据(比如 10000 条数据),然后虚拟一个表格隐藏掉不需要显示的数据。

    为了解决让浏览器渲染的大量 DOM 时候出现的性能问题,我们不能把 10000 条数据都渲染到页面,采用一种方式,只渲染可视范围内数据。 同时为表格设置一个滚动条,只有在滚动到需要显示的区域时候才渲染该区域的数据,减少的 DOM 数量。

    预览地址

    以上这是一个 10000 条数据的 Table,渲染后的 HTML 结构是:

    我们可以看到在 Table 中只渲染了 14 个 rs-table-row ,其中第一个和最后一个是没有 children, 只是一个拥有高度的占位符。 每一个 rs-table-row 都是绝对定位,所以即使 Table 中删除一个 Row, 或者新增一个 Row ,也不会改变其他 Row 的位置。 在这样的基础上,通过获取滚动条的滚动的位置,就很容易判断当前 Row 的 top 值是否在 Table 的可视范围内,同时更新所有的 Row。

    很多优秀的库都实现了这样的功能,原理基本一致,比如 react-virtualized 就提供 Table 组件,但是他不支持 Tree。

    树形表格

    在表格中展示树形数据的需求,我们见得比较多就像甘特图表格展示那样。它有子父层级关系,可以展开子节点。

    这样一个表格,很多 Table 组件都支持,但是如果同时需要支持虚拟化就相对比较麻烦,因为在展开关闭节点的时候需要重新计算显示的 DOM 以及设置滚动条的位置。

    rsuite Table 组件之前的版本中,渲染的树形表格的 DOM 结构是一棵 Tree。 所以首先需要把 Tree 拍平,转换一个一维数组,为每一个节点设置父节点,通过父节点的深度渲染 Tree 节点的相对位置。 然后就比较好处理,只需要在点击展开关闭节点按钮的时候,处理好数据的过滤。

    安装与使用

    rsuite 的 Table 组件的设计,对开发还是非常方便,通过 <Table><Column><Cell><HeaderCell> 组件定义结构,通过赋值data 属性渲染表格数据。

    安装

    npm install rsuite --save 

    如果你在项目只希望用到 Table, 不想安装整个 rsuite 库,你可以单独安装 rsuite-table

    示例代码:

    import { Table } from 'rsuite'; const { Column, HeaderCell, Cell } = Table; const data = [{ id: 1, name: 'foobar', email: '[email protected]' }]; ReactDOM.render( <Table height={400} data={data}> <Column width={70} align="center" fixed> <HeaderCell>编号</HeaderCell> <Cell dataKey="id" /> </Column> <Column width={200} fixed> <HeaderCell>姓名</HeaderCell> <Cell dataKey="name" /> </Column> <Column width={200}> <HeaderCell>邮箱</HeaderCell> <Cell dataKey="email" /> </Column> </Table> ); 

    最后

    最后,对于一个成熟的 Table 组件怎么能只有这点功能,所以它还支持:

    • 自定义调整列宽
    • 锁定列
    • 自动换行
    • 排序
    • 分页
    • 编辑
    • 合并单元格
    • 自定义单元格
    • 自动列宽
    • 可展开行

    剩下唯一的问题,就是您是否在项目中尝试它。

    4 条回复    2019-01-18 13:47:34 +08:00
    agdhole
        1
    agdhole  
       2019 年 1 月 18 日 via Android
    这个需求让我想到了上次的帖子“技术选型开除前端”
    xiwangzishi
        2
    xiwangzishi  
       2019 年 1 月 18 日
    @agdhole 哈哈哈,是的。
    fy
        3
    fy  
       2019 年 1 月 18 日
    @agdhole #1 记忆犹新
    chinvo
        4
    chinvo  
       2019 年 1 月 18 日
    @agdhole #1 印象深刻
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2661 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 03:19 PVG 11:19 LAX 19:19 JFK 22:19
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86