专栏名称: 前端外刊评论
最新、最前沿的前端资讯,最有深入、最干前端相关的技术译文。
目录
相关文章推荐
商务河北  ·  经开区“美•强•优”三重奏 ·  7 小时前  
前端早读课  ·  【第3453期】圈复杂度在转转前端质量体系中的应用 ·  17 小时前  
前端早读课  ·  【第3452期】React 开发中使用开闭原则 ·  昨天  
前端早读课  ·  【第3451期】前端 TypeError ... ·  2 天前  
51好读  ›  专栏  ›  前端外刊评论

ali-react-table:高性能 React 表格组件

前端外刊评论  · 公众号  · 前端  · 2020-04-16 08:00

正文

简介

在前端开发中,表格一直都是最复杂的组件之一。表格不仅要支持丰富的操作(排序、过滤、搜索、分页、自定义列等),还要有非常好的性能以展示大量数据。很多组件库(例如 fusion design,ant design)提供了功能丰富的表格组件,这些表格一开始没有过多考虑性能问题,往往是后面遇到性能瓶颈问题时才考虑添加虚拟滚动特性,但此时过多的表格功能使得性能优化的难度非常高。

ali-react-table (https://github.com/alibaba/ali-react-table)是我们小组开发的高性能 React 表格组件,我们在一开始就考虑了表格的性能,为其添加了内置的虚拟滚动特性。虚拟滚动会在数据量较大时自动开启,轻松展示一万行/一万列以上的数据。虚拟滚动是表格的核心特性之一,在为表格实现新功能时,我们会确保新功能不与虚拟滚动冲突。

表格组件的基本用法和 antd/fusion 表格类似,传入 dataSource 来指定表格的数据源,传入 columns 来对表格的列进行配置。

import { BaseTable } from 'ali-react-table'

function BasicUsage({
  const dataSource = [
    { prov'湖北省'confirm54406cure4793dead1457t'2020-02-15 19:52:02' },
    { prov'广东省'confirm1294cure409dead2t'2020-02-15 19:52:02' },
    { prov'河南省'confirm1212cure390dead13t'2020-02-15 19:52:02' },
    { prov'浙江省'confirm1162cure428dead0t'2020-02-15 19:52:02' },
    { prov'湖南省'confirm1001cure417dead2t'2020-02-15 19:52:02' },
  ]

  const columns = [
    { code'prov'name'省份'width150 },
    { code'confirm'name'确诊'width100align'right' },
    { code'cure'name'治愈'width100align'right' },
    { code'dead'name'死亡'width100align'right' },
    { code't'name'更新时间'width180 },
  ]
  return <BaseTable dataSource={dataSource} columns={columns} />
}

虚拟滚动

当数据量较大时,表格会自动开启虚拟滚动。

锁列与单元格合并

在维度、指标数量较多情况下,设置 column.lock=true 可以在表格左侧或右侧锁定指定的列,提升交互体验。

在更复杂的情况下,可以设置 column.getSpanRect 来指定单元格的合并情况;column.getSpanRect 返回每个单元格被合并之后的矩形位置,在渲染表格时,BaseTable 会根据单元格的位置和对应的 spanRect,来为单元格动态设置 rowSpan/colSpan,使得在虚拟滚动场景下合并单元格依然可以生效。

基于这些实用的表格特性,我们可以在表格上进行深度定制与二次开发,实现下钻、右键菜单、交叉表/透视表、收拢/展开等功能。同时表格内置的虚拟滚动保证了大数据量下表格仍具有很好的性能,上层使用者不需要担心性能问题。

基于 BaseTable 的一个简单的透视表 demo(在线 demo)。

表格功能拓展

BaseTable 是一个相对底层的 React 组件,仅提供了基本的表格渲染功能。为了方便对表格进行功能拓展,我们为 BaseTable 设计了一个简单的拓展方案,然后我们基于该方案实现了一些常见的表格功能,包括排序、树状模式、列高亮等。

我们知道 BaseTable 基于 dataSource 和 columns 来渲染表格,按照一定的规则对 dataSource/columns 进行包装和转换,可以改变 dataSource/columns 的值或渲染输出,实现特定的功能。

type Transform = (input: T) => T

type TableTransform = Transform  columns: ArtTableColumn[]
  dataSource: any[]
}>

TableTransform (后面简称 transform)是一个纯函数,输入列配置 + 数据源,输出一份新的列配置 + 数据源。每一个 transform 通过对 dataSource/columns 的包装和转换以实现一个新的特性。注意到每个 transform 的输入和输出的类型相同,我们可以将多个 transform 串联以实现不同功能的组合。

ali-react-table/biz 提供了一些常见表格功能的 transform,下面以「排序和列高亮两个功能的组合」为例介绍 transform 的使用方式。

对应的代码如下:

import { ArtColumn, BaseTable } from 'ali-react-table'
import { applyTransforms, commonTransforms } from 'ali-react-table/biz'
import React, { useState } from 'react'

function SingleSortExample({
  const { isLoading, dataSource } = useProvinceDataSource()

  const columns: ArtTableColumn[] = [
    // 通过 features.sortable 来标记 可排序的列
    { code'provinceName'name'省份'features: { sortabletrue } },
    { code'confirmedCount'name'确诊'features: { sortabletrue } },
    { code'curedCount'name'治愈'features: { sortabletrue } },
    { code'deadCount'name'死亡'features: { sortabletrue } },
    { code'updateTime'name'最后更新时间' },
  ]

  // transform 都是纯函数,所需的额外状态需要上层提供,这里使用 useState 来快速创建状态
  const [hoverColIndex, onChangeHoverColIndex] = useState(-1)
  const [sorts, onChangeSorts] = useState([
    { code'deadCount'order'desc' },
  ])

  const renderData = applyTransforms(
    { columns, dataSource },
    commonTransforms.columnHover({ hoverColIndex, onChangeHoverColIndex }),
    // 设置 sort.mode=multiple 可以使用多列排序
    commonTransforms.sort({ mode'single', sorts, onChangeSorts }),
  )

  // applyTransform 是使用多个 transform 的辅助函数
  // 上面的代码相当于:
  // input = { dataSource, columns }
  // t1 = commonTransforms.columnHover(...)
  // t2 = commonTransforms.sort(...)
  // renderData = t2(t1(input))

  return (
    <BaseTable
        dataSource={renderData.dataSource}
        columns={renderData.columns}
    />

  )
}

相比于原来的「直接通过 props 设置表格配置」的方式,transform 使用起来更麻烦一些,但它的优势也非常明显:

  • 对于用户:

  • 按需引入 transform,多个 transform 可组合性较好,降低多个功能之间的冲突概率

  • 因为原来表格封装了所有功能,多个功能之间非常容易发生冲突

  • 表格功能不满足业务需求时,可自行实现自定义 transform,与 commonTransforms 配合使用







请到「今天看啥」查看全文