使用Table.render优化页面列表展示

发布时间:2023-05-18

一、优点:

Table组件是Antd Design React UI库中非常强大的一个组件,它可以轻松地将数据渲染成表格,并且可以对表格进行排序、分页等操作。当需要渲染大量的数据时,React开发人员会使用分页功能去将数据分页展示,但是如果数据较多,分页展示将会使用户体验下降。此时就可以使用Table组件的render属性来优化页面展示效果,即将数据以虚拟表格的形式展示在页面中。当用户上下滑动虚拟表格时,只渲染可视区域内的数据,其他数据不会被渲染,大大提高了页面性能。

二、使用:

要使用Table.render优化页面列表展示,我们需要引入antd的Table组件和React-virtualized组件:

import { Table } from 'antd';
import { AutoSizer, Column } from 'react-virtualized';
import 'react-virtualized/styles.css';

其中AutoSizer是一个包裹组件,会根据其子元素的高度和宽度来自动计算出表格应该占用的宽和高,而Column则是Table组件每一列的映射,可以在其内部定义列的宽度、对齐方式等。 接下来,我们需要修改Table组件。

render() {
    const { data, columns, rowKey } = this.props;
    return (
        <AutoSizer>
            {({ width, height }) => (
                <Table
                    {...this.props}
                    size="middle"
                    dataSource={data}
                    pagination={false}
                    rowKey={rowKey}
                    scroll={{ x: width, y: height }}
                    className="virtual-table"
                    components={{
                        body: {
                            wrapper: VirtualBody,
                            row: VirtualRow,
                        },
                    }}
                >
                    {columns.map((column) => (
                        <Column
                            key={column.dataIndex}
                            width={column.width}
                            align={column.align}
                            headerRenderer={() => (
                                <div className="table-header">
                                    <span>{column.title}</span>
                                </div>
                            )}
                            cellRenderer={({ rowData }) => (
                                <div className="table-cell">
                                    {column.render(rowData[column.dataIndex])}
                                </div>
                            )}
                            dataKey={column.dataIndex}
                        />
                    ))}
                </Table>
            )}
        </AutoSizer>
    );
}

我们将Table组件的body和row属性改为了VirtualBody和VirtualRow,而VirtualBody是React-virtualized提供的包裹组件,它可以根据可视区域内的行数据来渲染表格行。 接下来,我们需要自定义VirtualRow和VirtualBody组件。VirtualRow组件用来渲染每一行数据,而VirtualBody组件则用于渲染表格中所有的数据。虚拟表格中只会渲染可视区域内的数据,所以我们需要根据scrollTop和scrollTop+clientHeight计算出数据的开始和结束位置,只渲染可视区域内的数据:

const Row = ({ className, columns, index, key, style }) => (
    <div
        key={key}
        className={classNames(className, 'virtual-row')}
        style={style}
    >
        {columns.map((column) => (
            <div key={column.dataIndex} className="table-cell">
                {column.render(data[index][column.dataIndex])}
            </div>
        ))}
    </div>
);
const VirtualRow = ({ index, style, data }) => (
    <Row
        index={index}
        style={style}
        className={data[index]._index % 2 === 0 ? 'even' : 'odd'}
        columns={data.columns}
    />
);
const VirtualBody = ({ className, style, columns, dataSource, onScroll }) => {
    const { scrollTop, clientHeight } = event.target;
    const startIndex = Math.floor(scrollTop / 35);
    const endIndex = Math.min(startIndex + Math.ceil(clientHeight / 35), dataSource.length);
    const tableData = {
        columns,
        startIndex,
        endIndex,
    };
    return (
        <div
            className={classNames(className, 'virtual-body')}
            onScroll={onScroll}
        >
            {tableData &&
                tableData.columns &&
                tableData.columns.length > 0 &&
                dataSource.slice(startIndex, endIndex).map((item, index) => (
                    <VirtualRow
                        data={dataSource}
                        index={startIndex + index}
                        key={index}
                        style={{
                            top: `${35 * (index - startIndex)}px`,
                        }}
                    />
                ))}
        </div>
    );
};

我们来解析一下代码: 首先,我们定义了一个Row组件,用于将所有的行数据渲染成表格的一行;接着,我们定义了VirtualRow组件,它通过计算开始和结束位置来动态渲染每一行数据;最后,我们定义了VirtualBody组件,它通过计算可视区域内的数据,并调用VirtualRow组件来渲染出所有的行数据。

三、优化效果:

使用Table.render优化页面列表展示能够有效地提高页面性能,目前很多在线商城、社交平台、新闻网站都采用了该技术优化其列表展示效果。