Skip to main content

交叉树状表格

交叉树状表格(CrossTreeTable)与交叉表(CrossTable)类似,但在表格左侧提供了树状展开/收拢的能力,更适用于日常业务开发。

主要特性#

  • 不依赖特定组件库,可独立使用
  • 简单、一致的 API 与渲染模型:左树 + 上树 => 表格
  • 高性能:数据量较大时,自动开启虚拟滚动

用法#

CrossTreeTable 主要由以下几个部分组成:

  • primaryColumn 描述表格第一列
  • 通过 leftTree 描述表格左侧的树状结构;
  • 通过 topTree 描述表格上方的树状结构;
  • 通过 getValue 来定义每个单元格内容;
  • CrossTreeTable 会根据 leftTree/topTree 来渲染表格结构,并调用 getValue 获取单元格的内容
// prettier-ignore<CrossTreeTable  // 推荐为 CrossTreeTable 设置一个默认列宽  defaultColumnWidth={100}
  // 非受控用法  defaultOpenKeys={[leftTree[0].key]}
  // 受控用法  // openKeys={openKeys}  // onChangeOpenKeys={nextOpenKeys => { /* update openKeys */ }}
  // 表格第一列的配置  primaryColumn={{ lock: true, name: '数据维度', width: 200 }}
  leftTree={leftTree}  topTree={topTree}  getValue={(leftNode, topNode) => {    // 自定义的取数逻辑,针对每个单元格都会调用一次    // leftNode 表示当前单元格对应的左侧树节点,topNode 是对应的上方树节点  }}
  // 可选的自定义的渲染逻辑  render={(value, leftNode, topNode) => {    return value  }}/>
预览点击展开或收拢

2021年 学习计划

源码点击展开或收拢

leftTree 的结构 / topTree 的结构#

leftTree/topTree 都是一个具有 key/value/children 嵌套结构的数组,详见 交叉表文档.

注意 CrossTreeTable 对于 leftTree 和 topTree 的处理有所不同:

  • leftTree 中的每个节点对应表格中的一行,包括叶子节点和非叶节点
  • topTree 中的叶子节点对应 表格上的一列

其他 props#

CrossTreeTable 的底层依赖了 BaseTable,故两者的 props 大部分是相同的。两者的不同点具体如下:

  • CrossTreeTable 没有 dataSource 和 columns
    • 表格结构由 leftTree 和 rightTree 提供,而单元格内容由 getValue 提供
    • 单元格渲染内容可使用 render 进行自定义;单元格的 props(即表格内的 td 元素)可使用 getCellProps 进行自定义
  • CrossTreeTable 没有 primaryKey
    • CrossTreeTable 左侧树中每个节点都有一个唯一的 key 值,故不再需要上层指定 primaryKey
  • 其他新增的 props
    • CrossTreeTable 使用 primaryColumn 来描述 表格第一列的配置
    • openKeys/onChangeOpenKeys/defaultOpenKeys:树状模式下展开节点的 key 数组

CrossTreeTable props 具体如下:

export interface CrossTreeTableProps extends Omit<BaseTableProps, 'dataSource' | 'columns' | 'primaryKey'> {  primaryColumn: CrossTableLeftMetaColumn  leftTree: LeftCrossTreeNode[]  topTree: TopCrossTreeNode[]
  defaultOpenKeys?: string[]  openKeys?: string[]  onChangeOpenKeys?(nextOpenKeys: string[]): void
  getValue(leftNode: LeftCrossTreeNode, topNode: TopCrossTreeNode, leftDepth: number, topDepth: number): any  render?(    value: any,    leftNode: LeftCrossTreeNode    topNode: TopCrossTreeNode,    leftDepth: number,    topDepth: number,  ): ReactNode  getCellProps?(    value: any,    leftNode: LeftCrossTreeNode,    topNode: TopCrossTreeNode,    leftDepth: number,    topDepth: number,  ): CellProps}
export interface CrossTableLeftMetaColumn extends Omit<ArtColumnStaticPart, 'hidden'> {  /** 自定义渲染方法 */  render?(leftNode: LeftCrossTreeNode, leftDepth: number): ReactNode
  /** 自定义的获取单元格 props 的方法 */  getCellProps?(leftNode: LeftCrossTreeNode, leftDepth: number): CellProps}

不要被长长的 TypeScript 类型代码吓到,CrossTreeTable 的 props 其实和 BaseTable 差别不大。

交叉树状表格定制#

CrossTreeTable 的底层仍是 <BaseTable />

对 CrossTreeTable 进行定制时,可以先通过 buildCrossTreeTable 根据 CrossTreeTable 的输入生成 dataSource / columns,进行一些自定义的处理,然后再将处理好的数据传给 BaseTable,并注意为 BaseTable 设置 primaryKey={ROW_KEY}

可以使用 pipeline 进行表格功能拓展(具体可以参考这个示例),但因为 CrossTreeTable 本身很复杂,只有一部分比较简单的 pipeline feature 可以和 CrossTreeTable 一起工作.

import { BaseTable } from 'ali-react-table'import { buildCrossTreeTable, ROW_KEY } from 'ali-react-table/pivot'
function MyComplexTable() {  // 将「传给 CrossTreeTable 的参数」传给 buildCrossTreeTable  const { dataSource, columns } = buildCrossTreeTable({    leftTree,    topTree,    getValue,    render,
    // 调用 buildCrossTreeTable 必须传入一份受控的 openKeys 状态    openKeys: ['a', 'b', 'c'],    onChangeOpenKeys(nextOpenKeys) {},
    // 这里也支持 CrossTreeTable 的其他 props  })
  // 在这里可以对 dataSource 和 columns 进行一定的处理后,再将数据传递给 BaseTable
  return (    <BaseTable      className="my-complex-table"      primaryKey={ROW_KEY}      defaultColumnWidth={100}      dataSource={dataSource}      columns={columns}    />  )}