虚拟化表格 beta

随着 Web 技术的不断发展,表格组件一直是 Web 应用中最受欢迎的组件之一,尤其是在仪表盘和数据分析场景中。对于表格 V1,即使只有 1000 条数据记录,由于性能不佳,使用起来也会非常烦人。

使用虚拟化表格,您可以在眨眼之间渲染大量数据。

提示

该组件仍在测试中,使用风险自负。如果您发现任何错误或问题,请在 GitHub 上报告给我们修复。此外,还有一些 API 在本文档中没有提及,其中一些尚未完全开发,因此在这里没有提及。

即使虚拟化表格效率很高,当数据负载过大时,您的网络内存大小也可能成为应用的瓶颈。因此请记住,虚拟化表格绝不是万能的解决方案,请考虑对数据进行分页、添加筛选器等。

基础用法

让我们通过渲染一个包含 10 列和 1000 行的基本示例来演示虚拟化表格的性能。

自动调整尺寸

当您不想手动将 widthheight 属性传递给表格时,您可以用 AutoResizer 包装表格组件。这将自动为您更新宽度和高度。

调整浏览器大小以查看其工作原理。

提示

请确保 AutoResizer 的父节点具有固定的高度,因为其默认高度值设置为 100%。或者,您可以通过将 style 属性传递给 AutoResizer 来定义它。

自定义单元格渲染器

当然,您可以根据需要渲染表格单元格。这里有一个如何自定义单元格的简单示例。

带选择功能的表格

使用自定义单元格渲染器为您的表格启用选择功能。

行内编辑

就像我们上面演示的选择功能一样,您可以使用相同的方法来启用行内编辑。

带状态的表格

您可以高亮显示您的表格内容,以区分“成功、信息、警告、危险”和其他状态。

要自定义行的外观,请使用 row-class-name 属性。例如,每第 10 行使用 bg-blue-200 类高亮显示,每第 5 行使用 bg-red-100 类高亮显示。

带固定行的表格

您可以让一些行固定在表格顶部,这可以通过使用 fixed-data 属性非常容易地实现。

您可以根据滚动事件动态设置固定行,如本例所示。

带固定列的表格

如果您出于某种原因希望列固定在左侧或右侧,可以通过向表格添加特殊属性来实现。

您可以将列的属性 fixed 设置为 true(表示 FixedDir.LEFT)、FixedDir.LEFTFixedDir.RIGHT

表头分组

通过自定义表头渲染器,您可以像本例中那样对表头进行分组。

提示

在这种情况下,我们使用了 JSX 功能,该功能在演练场中不受支持。您可以在本地环境或在线 IDE(如 codesandbox)中尝试它们。

建议您使用 JSX 编写表格组件,因为它包含 VNode 操作。

筛选

虚拟化表格提供了自定义表头渲染器,用于创建自定义表头。然后,我们可以利用这些来渲染筛选器。

可排序

您可以使用排序状态对表格进行排序。

受控排序

您可以根据需要定义多个可排序列。请记住,如果定义多个可排序列,UI 可能会让用户感到困惑,因为不清楚当前正在对哪一列进行排序。

交叉悬停

在处理大型列表时,很容易忘记当前正在访问的行和列。在这种情况下,使用此功能会非常有帮助。

列合并

虚拟化表格不使用内置的 table 元素,因此 colspanrowspan 的行为与表格V1略有不同。但是,通过自定义行渲染器,这些功能仍然可以实现。在本节中,我们将演示如何实现这一点。

行合并

既然我们已经介绍了列合并,值得注意的是我们也有行合并。它与列合并有点不同,但思想基本相同。

行合并和列合并一起使用

我们可以将行合并和列合并结合起来,以满足您的业务目标!

树形数据

虚拟表格还可以以树形结构渲染数据。通过单击箭头图标,您可以展开或折叠树节点。

动态行高

虚拟表格能够渲染具有动态高度的行。如果您正在处理数据并且不确定内容大小,此功能非常适合渲染能够适应内容高度的行。要启用此功能,请传入 estimated-row-height 属性。估计高度与实际内容越接近,渲染体验就越流畅。

提示

每一行的高度在渲染行时动态测量。因此,如果您试图显示大量数据,UI 可能会跳动。

详情视图

使用动态高度渲染,您还可以在表格中显示详细视图。

当您想显示总结性消息或信息时,渲染一个自定义页脚。

自定义空状态渲染器

渲染一个自定义的空元素。

遮罩层

当您想显示加载指示器或其他内容时,在表格上方渲染一个遮罩层。

手动滚动

使用 Table V2 提供的方法,通过所需的偏移量/行数进行手动/编程滚动。

提示

scrollToRow 的第二个参数是滚动策略,默认为 auto,它会自行计算滚动位置。如果您希望滚动到特定位置,可以自己定义策略。可用选项为 "auto" | "center" | "end" | "start" | "smart"

smartauto 的区别在于 autosmart 滚动策略的一个子集。

TableV2 API

TableV2 属性

名称描述类型默认值
cache提前渲染的行数,以提高性能number2
estimated-row-height用于渲染动态高度行的估计行高number
header-class传递给表头包装器的自定义类名string / Function<HeaderClassGetter>
header-props传递给表头组件的自定义 props 名称object / Function<HeaderPropsGetter>
header-cell-props传递给表头单元格组件的自定义 props 名称object / Function<HeaderCellPropsGetter>
header-height表头的高度由 height 设置。如果给定一个数组,它将渲染等于其长度的表头行number/ number[]50
footer-height页脚元素的高度,如果提供,将参与表格高度的计算。number0
row-class传递给行包装器的自定义类名string / Function<RowClassGetter>
row-key每一行的键,如果未提供,将是行的索引string / Symbol / numberid
row-props传递给行组件的自定义 props 名称object / Function<RowPropsGetter>
row-height每一行的高度,用于计算表格的总高度number50
row-event-handlers附加到每一行的处理程序集合object<RowEventHandlers>
cell-props传递给每个单元格(表头单元格除外)的额外 propsobject / Function<CellPropsGetter>
columns列定义的数组。Column[]
data要在表格中渲染的数据数组。Data[][]
data-getter一个用于自定义从数据源获取数据的方法。Function<DataGetter<T>>
fixed-data用于在主内容上方和表头下方渲染行的数据object<Data>
expand-column-key指示哪一列是可展开的列键string
expanded-row-keys展开行的键数组,可与 v-model 一起使用KeyType[]
default-expanded-row-keys默认展开行的键数组,非响应式KeyType[]
class虚拟表格的类名,将应用于所有三个表格(左、右、主)string / array / object
fixed指示表格列宽是固定的还是灵活的标志。booleanfalse
width 必填表格的宽度number
height 必填表格的高度number
max-height表格的最大高度number
indent-size树形表格的水平缩进number12
h-scrollbar-size指示表格的水平滚动条大小,用于防止水平和垂直滚动条重叠number6
v-scrollbar-size指示表格的垂直滚动条大小,用于防止水平和垂直滚动条重叠number6
scrollbar-always-on如果为 true,滚动条将始终显示,而不是在鼠标悬停在表格上时显示booleanfalse
sort-by排序指示器object<SortBy>{}
sort-state多重排序指示器object<SortState>undefined

TableV2 插槽

名称类型
cellobject<CellSlotProps>
headerobject<HeaderSlotProps>
header-cellobject<HeaderCellSlotProps>
rowobject<RowSlotProps>
footer
empty
overlay

TableV2 事件

名称描述参数
column-sort当列排序时调用object<ColumnSortParam>
expanded-rows-change当展开的行发生变化时调用KeyType[]
end-reached当到达表格末尾时调用。回调函数包含剩余距离,通常是滚动条的高度。Function
scroll滚动后调用object<ScrollParams>
rows-rendered当行被渲染时调用object<RowsRenderedParams>
row-expand当通过单击箭头图标展开/折叠树节点时调用object<RowExpandParams>

TableV2 Exposes

方法描述参数
scrollTo滚动到给定位置Function
scrollToLeft滚动到给定的水平位置Function
scrollToTop滚动到给定的垂直位置Function
scrollToRow使用指定的滚动策略滚动到给定的行Function

提示

请注意,这些是 JavaScript 对象,因此您不能对这些属性使用 kebab-case(短横线命名法)

列属性

名称描述类型默认值
align表格单元格内容的对齐方式Alignmentleft
class列的类名string
key唯一标识KeyType
dataKey数据的唯一标识KeyType
fixed列的固定方向boolean / FixedDirfalse
flexGrowCSSProperties 的 flex grow,仅在非固定表格时有用number0
flexShrinkCSSProperties 的 flex shrink,仅在非固定表格时有用number1
headerClass用于自定义表头列类string
hidden该列是否不可见boolean
style列单元格的自定义样式,将与网格单元格合并object
sortable指示该列是否可排序boolean
title在表头单元格中渲染的默认文本string
maxWidth列的最大宽度number
minWidth列的最小宽度number
width 必填列的宽度number
cellRenderer自定义单元格渲染器VueComponent / (props: CellRenderProps) => VNode
headerCellRenderer自定义表头渲染器VueComponent / (props: HeaderRenderProps) => VNode

类型定义

显示类型声明
ts
type HeaderClassGetter = (param: {
  columns: Column<any>[]
  headerIndex: number
}) => string

type HeaderPropsGetter = (param: {
  columns: Column<any>[]
  headerIndex: number
}) => Record<string, any>

type HeaderCellPropsGetter = (param: {
  columns: Column<any>[]
  column: Column<any>
  columnIndex: number
  headerIndex: number
  style: CSSProperties
}) => Record<string, any>

type RowClassGetter = (param: {
  columns: Column<any>[]
  rowData: any
  rowIndex: number
}) => string

type RowPropsGetter = (param: {
  columns: Column<any>[]
  rowData: any
  rowIndex: number
}) => Record<string, any>

type CellPropsGetter = (param: {
  column: Column<any>
  columns: Column<any>[]
  columnIndex: number
  cellData: any
  rowData: any
  rowIndex: number
}) => void

type DataGetterParams<T> = {
  columns: Column<T>[]
  column: Column<T>
  columnIndex: number
} & RowCommonParams

type DataGetter<T> = (params: DataGetterParams<T>) => T

type CellRenderProps<T> = {
  cellData: T
  column: Column<T>
  columns: Column<T>[]
  columnIndex: number
  rowData: any
  rowIndex: number
}

type HeaderRenderProps<T> = {
  column: Column<T>
  columns: Column<T>[]
  columnIndex: number
  headerIndex: number
}

type ScrollParams = {
  xAxisScrollDir: 'forward' | 'backward'
  scrollLeft: number
  yAxisScrollDir: 'forward' | 'backward'
  scrollTop: number
}

type CellSlotProps<T> = {
  column: Column<T>
  columns: Column<T>[]
  columnIndex: number
  depth: number
  style: CSSProperties
  rowData: any
  rowIndex: number
  isScrolling: boolean
  expandIconProps?:
    | {
        rowData: any
        rowIndex: number
        onExpand: (expand: boolean) => void
      }
    | undefined
}

type HeaderSlotProps = {
  cells: VNode[]
  columns: Column<any>[]
  headerIndex: number
}

type HeaderCellSlotProps = {
  class: string
  columns: Column<any>[]
  column: Column<any>
  columnIndex: number
  headerIndex: number
  style: CSSProperties
  headerCellProps?: any
  sortBy: SortBy
  sortState?: SortState | undefined
  onColumnSorted: (e: MouseEvent) => void
}

type RowCommonParams = {
  rowData: any
  rowIndex: number
}

type RowEventHandlerParams = {
  rowKey: KeyType
  event: Event
} & RowCommonParams

type RowEventHandler = (params: RowEventHandlerParams) => void
type RowEventHandlers = {
  onClick?: RowEventHandler
  onContextmenu?: RowEventHandler
  onDblclick?: RowEventHandler
  onMouseenter?: RowEventHandler
  onMouseleave?: RowEventHandler
}

type RowsRenderedParams = {
  rowCacheStart: number
  rowCacheEnd: number
  rowVisibleStart: number
  rowVisibleEnd: number
}

type RowSlotProps = {
  columns: Column<any>[]
  rowData: any
  columnIndex: number
  rowIndex: number
  data: any
  key: number | string
  isScrolling?: boolean
  style: CSSProperties
}

type RowExpandParams = {
  expanded: boolean
  rowKey: KeyType
} & RowCommonParams

type Data = {
  [key: KeyType]: any
  children?: Array<any>
}

type FixedData = Data

type KeyType = string | number | symbol

type ColumnSortParam<T> = { column: Column<T>; key: KeyType; order: SortOrder }

enum SortOrder {
  ASC = 'asc',
  DESC = 'desc',
}

enum Alignment {
  LEFT = 'left',
  CENTER = 'center',
  RIGHT = 'right',
}

type SortBy = { key: KeyType; Order: SortOrder }
type SortState = Record<KeyType, SortOrder>

常见问题

如何在第一列渲染一个带复选框的列表?

由于您可以定义自己的单元格渲染器,您可以像自定义单元格渲染器示例那样自己渲染 checkbox,并自行维护其状态。

为什么虚拟化表格提供的功能比 TableV1 少?

对于虚拟化表格,我们打算提供较少的功能,让用户根据需要实现自己的功能。集成太多功能会使代码难以维护,而且对于大多数用户来说,基本功能已经足够了。一些关键功能尚未开发。我们很乐意听取您的意见。加入 Discord 保持关注。

来源

组件样式文档

贡献者