Skip to content

FxTableV2 虚拟滚动表格

基于 FxFixedSizeGrid / FxDynamicSizeGrid@fx/components)的虚拟滚动表格,只渲染可见区域的行列,适合大数据量(万级以上)表格。UI 框架无关:纯 Vue + @fx/styles token + useNamespace('table-v2')

核心能力:固定列(左/右)、单列/多列排序、自定义单元格 / 表头渲染函数、固定底部、空数据、遮罩层、动态行高、手动滚动控制、多层表头、展开行、树形数据。

基础用法

columns 定义列(key / title / dataKey / width,其中 width 必填),data 为数据数组,width / height 必填。下方示例渲染 10000 行,仅可见行参与渲染。

固定列

fixed 属性开启固定列布局后,表格拆分为 main / left / right 三个区域同步滚动。列上设置 fixed: true(默认左侧)、fixed: FixedDir.LEFTfixed: FixedDir.RIGHT 固定到对应方向。

排序

列上设置 sortable: true 后表头出现排序按钮。配合 sort-by(单列受控排序,{ key, order })与 column-sort 事件实现受控排序;排序方向取值用 SortOrder.ASC / SortOrder.DESC

空数据

data 为空数组时显示空数据占位,可用 empty 具名插槽自定义内容。

固定底部

footer-height 设置底部高度(默认 0 即不显示),用 footer 具名插槽自定义底部内容,底部不参与纵向虚拟滚动。

自定义行样式

row-class 传入字符串或 ({ columns, rowData, rowIndex }) => string 回调,按行返回 className。

遮罩层

overlay 具名插槽覆盖在表格之上(绝对定位),常用于加载中遮罩。插槽内容自行定位。

手动滚动

通过 ref 拿到实例后调用 scrollTo / scrollToLeft / scrollToTop / scrollToRow 编程式滚动。

自适应容器

FxAutoResizer 包裹表格,通过默认插槽把容器实测的 { width, height } 传给表格,表格随容器尺寸变化自适应。

多列排序

sort-state(多列排序状态对象,key → order)配合 column-sort 事件实现多列受控排序,每列独立维护排序方向。

自定义单元格

列上设置 cellRenderer 自定义单元格渲染(返回 VNode),headerCellRenderer 自定义表头单元格。

行选择

在列上用 cellRenderer + FxCheckbox 渲染行选择框,headerCellRenderer 渲染表头全选框(含半选态)。

动态行高

设置 estimated-row-height 后启用动态行高模式,行高随单元格内容自适应(配合 cellRenderer 渲染不等高内容)。

跨表区同列高亮

cell-props 回调给每个单元格打标记 + 绑定 mouseenter / mouseleave,配合根 class 实现 main / left / right 三表区同一列联动高亮。

合并单元格

通过 row 具名插槽拿到 { cells, columns, rowData, rowIndex },用 cloneVNode 修改单元格 style(累加宽度 / 拉高高度)并置空被覆盖的 cell,实现列合并 / 行合并。

展开行详情

expand-column-key 指定展开列,行数据携带 children 作为展开内容;用 row 插槽判断展开行(rowData.detail)渲染详情,配合 estimated-row-height 让详情行自适应高度。

树形数据

扁平数据按 parentId 归集为树后传入,expand-column-key 指定展开列,v-model:expanded-row-keys 双向绑定展开状态,展开后子节点自动扁平化插入并按深度缩进。

筛选

headerCellRenderer 自定义表头,配合 FxPopover 渲染弹出式筛选面板:点击筛选图标弹出勾选条件与确认 / 重置按钮,确认后切换数据集。

单元格编辑

cellRenderer 根据行内 editing 标记在触发器(div)与编辑器(FxInput)间切换,点击进入编辑、失焦 / 回车退出。

多层表头

header-height 传数组开启多层表头,用 header 具名插槽自定义每一层(拿到 { cells, columns, headerIndex }),把相邻列合并成分组表头;固定列占位用 placeholderSign 识别。

粘性行

fixed-data 传入不参与滚动的固定行(粘在底部),配合 scroll 事件按滚动位置更新粘性行内容、row-class 标记样式。

FxTableV2 API

FxTableV2 Attributes

属性说明类型默认值
columns列定义Column[][]
data行数据Record<PropertyKey, any>[][]
data-getter自定义取值函数(优先于 dataKey(params) => any
fixed-data固定在底部不参与滚动的数据any[]
row-key行 key 字段名或取值函数KeyType'id'
width表格总宽度(必填)number
height表格总高度(必填)number
max-height最大高度(超出滚动)number
row-height行高(固定行高模式)number50
estimated-row-height预估行高,设置后启用动态行高模式number
header-height表头高度,多层表头传数组number | number[]50
footer-height底部高度number0
fixed是否启用固定列布局(生成 main/left/right 三表区)booleanfalse
use-is-scrolling是否追踪滚动状态(注入 isScrollingbooleanfalse
indent-size缩进尺寸(树形 / 展开行)number12
icon-size展开图标尺寸number12
h-scrollbar-size横向滚动条尺寸number6
v-scrollbar-size纵向滚动条尺寸number6
scrollbar-always-on滚动条常驻显示booleanfalse
cache上下预渲染行数number2
header-class表头 classNamestring | HeaderClassNameGetter
header-props表头额外 propsobject | ExtractHeaderPropGetter
header-cell-props表头单元格额外 propsobject | ExtractHeaderCellPropGetter
row-class行 classNamestring | RowClassNameGetter
row-props行额外 propsobject | ExtractRowPropGetter
cell-props单元格额外 propsobject | ExtraCellPropGetter
class根 classNamestring
style根 styleCSSProperties
expand-column-key展开行列 keystring
expanded-row-keys受控展开行 keysKeyType[]
default-expanded-row-keys默认展开行 keys(非受控)KeyType[]
sort-by单列排序状态(受控)SortBy{}
sort-state多列排序状态(受控)SortState
row-event-handlers行事件处理集合RowEventHandlers

FxTableV2 Slots

名称说明参数
cell单元格默认内容(所有列共用){ cellData, rowData, rowIndex, column, columnIndex }
header-cell表头单元格默认内容(所有列共用){ column, columnIndex, headerIndex }
row自定义整行{ columns, rowData, rowIndex }
header自定义整行表头{ columns, headerIndex }
footer底部内容
empty空数据占位
overlay遮罩层(覆盖在表格之上)

单列自定义优先用 column.cellRenderer / column.headerCellRenderercell / header-cell 插槽对所有列生效。

FxTableV2 Events

事件名说明回调参数
column-sort列排序触发{ column, key, order }
scroll滚动触发{ scrollLeft, scrollTop }
row-expand行展开 / 收起{ expanded, rowData, rowIndex }
row-hover行 hover{ hovered, rowData, rowIndex }
row-height-change行高变化(动态行高)RowHeightChangedParams
expanded-rows-change展开行 keys 变化KeyType[]
end-reached滚动到底部remainDistance: number
rows-rendered行渲染范围变化{ rowCacheStart, rowCacheEnd, rowVisibleStart, rowVisibleEnd }

FxTableV2 Exposes

名称说明参数
scrollTo滚动到指定位置({ scrollLeft?, scrollTop? })
scrollToLeft滚动到横向位置(scrollLeft: number)
scrollToTop滚动到纵向位置(scrollTop: number)
scrollToRow滚动到指定行(row: number, strategy?: 'auto' | 'smart' | 'center' | 'start' | 'end')

Column

列定义(width 必填)。

属性说明类型
key列唯一标识(兼做排序 key)KeyType
data-key数据字段名(默认渲染取值用)KeyType
title列标题string
width列宽(px,必填)number
min-width最小列宽number
max-width最大列宽number
align排列方向'left' | 'center' | 'right'
fixed固定列:true 固定左侧,或指定方向true | FixedDir
flex-grow剩余空间分配number
flex-shrink空间收缩number
sortable是否可排序boolean
hidden是否隐藏boolean
class单元格 className(字符串或 getter)string | ClassNameGetter
header-class表头单元格 classNamestring | HeaderClassGetter
style列自定义样式CSSProperties
cell-renderer单元格自定义渲染函数CellRenderer
header-cell-renderer表头单元格自定义渲染函数HeaderCellRenderer

内置常量

排序方向与固定列方向用内置常量取值(避免硬编码字符串)。

ts
import { SortOrder, FixedDir, Alignment } from '@fx/components'

SortOrder.ASC   // 'asc'
SortOrder.DESC  // 'desc'
FixedDir.LEFT   // 'left'
FixedDir.RIGHT  // 'right'
Alignment.LEFT  // 'left'
Alignment.CENTER // 'center'
Alignment.RIGHT // 'right'

类型声明

展开查看完整类型定义
ts
type KeyType = string | number | symbol

type RowCommonParams = {
  rowData: any
  rowIndex: number
}

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

type CellRendererParams<T> = {
  cellData: T
} & RowCommonParams &
  ColumnCommonParams<T>

type HeaderCellRendererParams<T> = {
  headerIndex: number
} & ColumnCommonParams<T>

type ClassNameGetterParams<T> = {
  cellData: T
} & RowCommonParams &
  ColumnCommonParams<T>

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

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

type ClassNameGetter<T> = (params: ClassNameGetterParams<T>) => string

type HeaderClassGetter<T> = (
  params: ColumnCommonParams<T> & { headerIndex: number },
) => string

type CellRenderer<T> = (params: CellRendererParams<T>) => VNode

type HeaderCellRenderer<T> = (params: HeaderCellRendererParams<T>) => VNode

type HeaderClassNameGetter<T> = (params: {
  columns: Column<T>[]
  headerIndex: number
}) => string

type RowClassNameGetter<T> = (
  params: { columns: Column<T>[] } & RowCommonParams
) => string

type ExtraCellPropGetter<T> = (
  params: ColumnCommonParams<T> &
    RowCommonParams & { cellData: T; rowData: any }
) => any

type ExtractHeaderPropGetter<T> = (params: {
  columns: Column<T>[]
  headerIndex: number
}) => any

type ExtractHeaderCellPropGetter<T> = (
  params: ColumnCommonParams<T> & { headerIndex: number }
) => any

type ExtractRowPropGetter<T> = (
  params: { columns: Column<T>[] } & RowCommonParams
) => any

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

type ScrollPos = {
  scrollLeft: number
  scrollTop: number
}

type CellSlotProps<T> = {
  class: string
  columns: Column<T>[]
  column: Column<T>
  columnIndex: number
  cellData: T
  rowData: any
  rowIndex: number
  isScrolling: boolean
}

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 RowSlotProps = {
  cells: VNode[]
  columns: Column<any>[]
  depth: number
  style: CSSProperties
  rowData: any
  rowIndex: number
  isScrolling: boolean
}

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 RowExpandParams = {
  expanded: boolean
  rowKey: KeyType
} & RowCommonParams

type RowHoverParams = {
  event?: MouseEvent
  hovered: boolean
  rowKey: KeyType
} & Partial<RowCommonParams>

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

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

// 内置常量(const 对象,非 enum)
const SortOrder = {
  ASC: 'asc',
  DESC: 'desc',
} as const

const Alignment = {
  LEFT: 'left',
  CENTER: 'center',
  RIGHT: 'right',
} as const

const FixedDir = {
  LEFT: 'left',
  RIGHT: 'right',
} as const

常见问题

如何在首列渲染勾选框?

由于虚拟表格允许自定义单元格渲染,你可以像自定义单元格示例那样,通过 cellRenderer 自行渲染勾选框(FxCheckbox),并自行维护选中状态。参考行选择示例。

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

虚拟表格有意提供更少的开箱即用功能,让用户按需实现自己的业务逻辑。集成过多功能会使代码难以维护,对大多数用户而言基础功能已足够。部分关键特性尚未开发。

FxAutoResizer API

容器尺寸自适应组件,配合 FxTableV2 让表格填满父容器并随容器尺寸变化自适应。

FxAutoResizer Attributes

属性说明类型默认值
disable-width是否禁用宽度自适应booleanfalse
disable-height是否禁用高度自适应booleanfalse

FxAutoResizer Slots

名称说明参数
default自定义内容(通常放 FxTableV2){ width, height }