React 实现一个漂亮的 Table
概述对于企业级后台产品来说,Table 应该是使用最频繁的组件了,它通常比 Form 和 Chart 的使用还频繁。对于这么一个常用的组件,我们决定要把它从 RSuite 中单独出来开发,并且要具有一定的通用性,适应很多场景。 首先看一下,Table 完成的效果。
最开始促使我们去实现这个 Table 组件是因为产品经理希望表格可以像 Excel一样固定表头和列,我们都知道 HTML table 是不支持这个功能,但是在实际应用中,对于数据行多列多的情况下,固定表头和列非常有用,方便数据关联浏览。我们的组件库都是 React 的, 开源环境中也没有找到一个适合的我们的 Table 组件。 Ant Design 中的 Table 估计有些人用过,UI 比较漂亮,但是在固定表头和列的这个功能上我还是有些不满意,特别是要同时固定表头和列的时候,在 Retina 屏幕上,Ant Table 通过触摸板滚动表格,固定的区域和非固定的区域会对不整齐,看上去会抖动,这个体验不是特别好。我知道 facebook 的 FixedDataTable 针对这块的处理做的还不错,是一个好的参考,特别是大数据量渲染也不卡顿,但是有些功能也不能满足我们的业务场景,比如在要 Table 中呈现一个树形结构就没有这个功能。所以还是决定自己造这个轮子。 设计在 UI 的设计上符合 RSuite 的整体风格。 我们具体看一下组件的设计,整个 Table 提供了 5 个组件,分别是:
看一个简单的示例: npm i rsuite rsuite-table --save
import { Table,Column,HeaderCell,Cell } from 'rsuite-table';
<Table data={data} > <Column width={100} sort fixed resizable> <HeaderCell>ID</HeaderCell> <Cell dataKey="id" /> </Column> <Column width={100} sort resizable> <HeaderCell>Name</HeaderCell> <Cell dataKey="name" /> </Column> <Column width={100} sort resizable> <HeaderCell>Email</HeaderCell> <Cell dataKey="email" /> </Column> </Table>
这是一个简单 3 列的表格,接下来我们来看一下具体的功能点。 功能介绍锁定列表头是默认固定的不需要额外的配置,要固定列,需要在固定的列 <Column width={100} fixed> <HeaderCell>ID</HeaderCell> <Cell dataKey="id" /> </Column>
这个功能是所有功能里面最麻烦的,特别是表头和列同时固定的时候,前面我也提到过 Ant Design 的 Table 就存在一个问题,滚动的时候固定列和非固定列未对齐,以下是一个 Ant Design 的 Table 的一个截图和访问链接。 访问地址: https://ant.design/components/table-cn/#components-table-demo-fixed-columns-header 造成这个问题的主要原因是
我们的 Table 在处理上面两点以后,就解决了 Ant Design 的 Table 滚动存在的问题,当然如果大家有更好的方案,感谢你分享一下。 另外,Ant Table 有很多方面做得是比我们好的,比如它支持固定右侧的列,支持嵌套表格等等功能。
可调整列宽在表格中有些列的数据有长有短,不太好预测,但还是希望在一个单元格内显示,如果给列固定好一个宽度以后,那超出单元格的内容就会被截断隐藏,导致信息显示不完整。Excel 的列是可以调整宽度的,所以我们也希望列可以调整宽度,只需要在 <Column width={130} sortable> <HeaderCell>First Name</HeaderCell> <Cell dataKey="firstName" /> </Column>
自动设置列宽有一种情况,Table 在页面中的宽度比如是 <Table width={1000}> <Column width={100}> <HeaderCell>First Name</HeaderCell> <Cell dataKey="firstName" /> </Column> <Column flexGrow={1}> <HeaderCell>City</HeaderCell> <Cell dataKey="city" /> </Column> <Column flexGrow={2}> <HeaderCell>Company Name</HeaderCell> <Cell dataKey="companyName" /> </Column> </Table>
在
排序排序是一个基础的功能,在需要排序的列 <Table onSortColumn={(sortColumn, sortType)=>{ console.log(sortColumn,sortType); }} > <Column width={50} sortable> <HeaderCell>Id</HeaderCell> <Cell dataKey="id" /> </Column> <Column width={130} sortable > <HeaderCell>First Name</HeaderCell> <Cell dataKey="firstName" /> </Column> <!--... --> </Table>
分页提供了一个 function formatLengthMenu(lengthMenu) { return ( <div className="table-length"> <span> 每页 </span> {lengthMenu} <span> 条 </span> </div> ); } function formatInfo(total,activePage) { return ( <span>共 <i>{total}</i> 条数据</span> ); }
<TablePagination formatLengthMenu={formatLengthMenu} formatInfo={formatInfo} displayLength={100} total={500} onChangePage={this.handleChangePage} onChangeLength={this.handleChangeLength} />
看一下,效果:
树形表格先看一下树形表格的样子 渲染成树形的表格需要设置两个地方,首先 <Table data={data} isTree expand height={400}>
data 中的数据结构 [{
labelName: '汽车',status: 'ENABLED',children: [ { labelName: '梅赛德斯-奔驰',count: 460 } ... ] ... }]
自定义单元格单元格中的内容往往需要能交互的,比如设置为一个连接,或者 比如,显示一个图片,定义一个 const ImageCell = ({ rowData,dataKey,...props }) => ( <Cell {...props}> <img src={rowData[dataKey]} width="50" /> </Cell> );
用的时候: <Column width={200} > <HeaderCell>Avartar</HeaderCell> <ImageCell dataKey="avartar" /> </Column>
比如,要格式化日期,就定义一个 const DateCell = ({ rowData,...props }) => ( <Cell {...props}> {rowData[dataKey].toLocaleString()} </Cell> );
用的时候: <Column width={200} > <HeaderCell>Action</HeaderCell> <DateCell dataKey="date" /> </Column>
自定义行高 如果在实际应用中需要根据数据内容来定义行高,可以使用以下方式 <Table onRerenderRowHeight={(rowData) => { if (rowData.firstName === 'Janis') { return 30; } }} > ... </Table>
可编辑的表格可编辑的表格,只需要自定义一个 export const EditCell = ({ rowData,onChange,...props }) => { return ( <Cell {...props}> {rowData.status === 'EDIT' ? ( <input className="input" defaultValue={rowData[dataKey]} onChange={(event) => { onChange && onChange(rowData.id,event.target.value); }} /> ) : rowData[dataKey]} </Cell> ); };
遗留的问题
如果,你对这些问题有好的想法欢迎你 提交pull request。 如果,你在使用中存在任何问题,可以提交issues。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |