ワンクリックで
stk-table
StkTable Vue 虚拟滚动表格组件的完整 API 参考与使用指南。当需要生成、修改 StkTable 相关代码,或回答 StkTable 的用法、Props、Events、Slots、Methods、类型定义等问题时使用。
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
StkTable Vue 虚拟滚动表格组件的完整 API 参考与使用指南。当需要生成、修改 StkTable 相关代码,或回答 StkTable 的用法、Props、Events、Slots、Methods、类型定义等问题时使用。
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
| name | stk-table |
| description | StkTable Vue 虚拟滚动表格组件的完整 API 参考与使用指南。当需要生成、修改 StkTable 相关代码,或回答 StkTable 的用法、Props、Events、Slots、Methods、类型定义等问题时使用。 |
本文档专为 AI 编码助手设计,帮助 AI 理解并生成 StkTable 相关代码。
stk-table-vuenpm install stk-table-vue
import { StkTable } from 'stk-table-vue';
import type { StkTableColumn, Order, SortConfig, SortState, SortOption } from 'stk-table-vue';
import 'stk-table-vue/lib/style.css'; // 引入样式,一般在 main.js(全局) 引入一次。
其他可导出项:
// 工具函数
import { tableSort, insertToOrderedArray, strCompare, binarySearch } from 'stk-table-vue';
// 按需特性(Area Selection 需先注册再使用)
import { useAreaSelection, registerFeature, createFilterCell, createEditableCell } from 'stk-table-vue';
import type { FilterStatus, CreateFilterOptions, CreateEditableCellOptions } from 'stk-table-vue';
<template>
<StkTable
row-key="id"
:columns="columns"
:data-source="dataSource"
/>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { StkTable } from 'stk-table-vue';
import type { StkTableColumn } from 'stk-table-vue';
import 'stk-table-vue/lib/style.css';
interface RowData {
id: number;
name: string;
age: number;
}
const columns: StkTableColumn<RowData>[] = [
{ title: '名称', dataIndex: 'name', width: 150 },
{ title: '年龄', dataIndex: 'age', width: 100 },
];
const dataSource = ref<RowData[]>([
{ id: 1, name: '张三', age: 25 },
{ id: 2, name: '李四', age: 30 },
]);
</script>
| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
width | string | '' | 表格宽度 |
stripe | boolean | false | 斑马线条纹 |
theme | 'light' | 'dark' | 'light' | 主题 |
bordered | boolean | 'h' | 'v' | 'body-v' | 'body-h' | true | 边框线。'h'仅横线,'v'仅竖线,'body-v'仅表体竖线,'body-h'仅表体横线 |
showOverflow | boolean | false | 表体溢出省略号 |
showHeaderOverflow | boolean | false | 表头溢出省略号 |
fixedMode | boolean | false | 是否 table-layout:fixed |
headless | boolean | false | 隐藏表头 |
| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
rowHeight | number | 28 | 行高(px)。autoRowHeight=true时为期望行高 |
autoRowHeight | boolean | AutoRowHeightConfig<DT> | false | 可变行高 |
headerRowHeight | number | string | 28 | 表头行高 |
footerRowHeight | number | string | 28 | 表尾行高 |
| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
rowHover | boolean | true | hover 高亮行 |
rowActive | boolean | RowActiveOption<DT> | { enabled: true, disabled: ()=>false, revokable: true } | 点击选中行高亮 |
rowClassName | (row: DT, i: number) => string | undefined | () => '' | 行 className 回调 |
showTrHoverClass | boolean | false | 行 hover class |
| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
cellHover | boolean | false | hover 高亮单元格 |
cellActive | boolean | false | 点击选中高亮单元格 |
selectedCellRevokable | boolean | true | 再次点击取消选中 |
| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
columns | StkTableColumn<DT>[] | [] | 必填。列配置数组 |
dataSource | DT[] | [] | 必填。数据源 |
rowKey | string | ((row: DT) => string) | '' | 推荐。行唯一键 |
colKey | string | ((col) => string) | undefined | 列唯一键,默认取 col.key 或 col.dataIndex |
emptyCellText | string | ((option: {row, col}) => string) | '--' | 空值展示文字 |
| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
virtual | boolean | false | Y 轴虚拟滚动 |
virtualX | boolean | false | X 轴虚拟滚动(横向虚拟滚动按需设置列宽) |
autoResize | boolean | (() => void) | true | 自动重算虚拟滚动尺寸(非响应式) |
| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
cellFixedMode | 'sticky' | 'relative' | 'sticky' | 固定列实现方式(非响应式) |
fixedColShadow | boolean | false | 固定列阴影 |
| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
sortRemote | boolean | false | 服务端排序(不排数据) |
sortConfig | SortConfig<DT> | { emptyToBottom: false, stringLocaleCompare: false, sortChildren: false } | 排序配置 |
hideHeaderTitle | boolean | string[] | false | 隐藏表头 title |
| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
headerDrag | boolean | HeaderDragConfig<DT> | false | 表头拖拽排序(需 v-model:columns) |
colResizable | boolean | ColResizableConfig<DT> | false | 列宽可拖动(需 v-model:columns + 设列 width) |
colMinWidth | number | 10 | 拖动最小列宽 |
areaSelection | boolean | AreaSelectionConfig | false | 单元格拖拽选区 |
| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
seqConfig | { startIndex?: number } | {} | 序号列配置 |
expandConfig | { height?: number } | {} | 展开行配置(虚拟模式下需指定 height) |
dragRowConfig | DragRowConfig | {} | 行拖动配置 |
treeConfig | TreeConfig | {} | 树形配置 |
highlightConfig | HighlightConfig | {} | 高亮配置(duration 秒) |
footerData | DT[] | [] | 底部合计行数据 |
footerConfig | FooterConfig | { position: 'bottom' } | 底部配置 |
scrollRowByRow | boolean | 'scrollbar' | false | 整行滚动 |
smoothScroll | boolean | chrome < 85 ? true : false | 平滑滚动(低版本浏览器默认true) |
scrollbar | boolean | ScrollbarOptions | false | 自定义滚动条 |
showNoData | boolean | true | 显示暂无数据 |
noDataFull | boolean | false | 暂无数据撑满高度 |
experimental | ExperimentalConfig | {} | 实验性功能 |
StkTableColumn<T>)type StkTableColumn<T> = {
// 基础
dataIndex: keyof T & string; // 必填,取值字段名
title?: string; // 表头文字
key?: any; // 列唯一键,默认取 dataIndex
type?: 'seq' | 'expand' | 'dragRow' | 'tree-node'; // 特殊列类型
hidden?: boolean; // 隐藏列
// 尺寸
width?: string | number; // 列宽(横向虚拟滚动按需设置,未设置时默认100)
minWidth?: string | number; // 最小列宽
maxWidth?: string | number; // 最大列宽
// 对齐
align?: 'left' | 'center' | 'right';
headerAlign?: 'left' | 'center' | 'right';
// 样式
className?: string;
headerClassName?: string;
// 排序
sorter?: boolean | ((data: T[], option: { order: Order; column: any }) => T[]);
sortField?: keyof T; // 排序字段(默认 dataIndex)
sortType?: 'number' | 'string';
sortConfig?: Omit<SortConfig<T>, 'defaultSort'>;
// 固定
fixed?: 'left' | 'right' | null;
// 自定义渲染(返回 VNode,使用 h 函数或 Vue SFC 组件)
customCell?: CustomCell<CustomCellProps<T>, T>;
customHeaderCell?: CustomCell<CustomHeaderCellProps<T>, T>;
customFooterCell?: CustomCell<CustomFooterCellProps<T>, T>;
// 多级表头
children?: StkTableColumn<T>[];
// 合并单元格
mergeCells?: (data: {
row: T; col: StkTableColumn<T>;
rowIndex: number; colIndex: number;
}) => { rowspan?: number; colspan?: number } | undefined;
};
| type | 用途 | dataIndex |
|---|---|---|
'seq' | 序号列 | 设为 '' |
'expand' | 展开行 | 设为 '' |
'dragRow' | 行拖拽把手 | 设为 '' |
'tree-node' | 树节点(带展开箭头) | 对应的数据字段 |
| 事件名 | 回调参数 | 说明 |
|---|---|---|
sort-change | (col: StkTableColumn<DT> | null, order: Order, data: DT[], sortConfig: SortConfig<DT>) | 排序变化 |
row-click | (ev: MouseEvent, row: DT, { rowIndex: number }) | 行点击 |
row-dblclick | (ev: MouseEvent, row: DT, { rowIndex: number }) | 行双击 |
current-change | (ev: MouseEvent | null, row: DT | undefined, { select: boolean }) | 选中行变化 |
cell-selected | (ev: MouseEvent | null, { select: boolean, row: DT | undefined, col: StkTableColumn<DT> | undefined }) | 选中单元格变化 |
cell-click | (ev: MouseEvent, row: DT, col: StkTableColumn<DT>, { rowIndex: number }) | 单元格点击 |
cell-mouseenter | (ev: MouseEvent, row: DT, col: StkTableColumn<DT>) | 单元格鼠标进入 |
cell-mouseleave | (ev: MouseEvent, row: DT, col: StkTableColumn<DT>) | 单元格鼠标离开 |
cell-mouseover | (ev: MouseEvent, row: DT, col: StkTableColumn<DT>) | 单元格悬浮 |
cell-mousedown | (ev: MouseEvent, row: DT, col: StkTableColumn<DT>, { rowIndex: number }) | 单元格鼠标按下 |
header-cell-click | (ev: MouseEvent, col: StkTableColumn<DT>) | 表头单元格点击 |
header-row-menu | (ev: MouseEvent) | 表头右键 |
row-menu | (ev: MouseEvent, row: DT, { rowIndex: number }) | 行右键 |
scroll | (ev: Event, { startIndex: number, endIndex: number }) | 纵向滚动 |
scroll-x | (ev: Event) | 横向滚动 |
col-order-change | (dragStartKey: string, targetColKey: string) | 列拖拽排序完成 |
th-drag-start | (dragStartKey: string) | 列拖拽开始 |
th-drop | (targetColKey: string) | 列拖拽放下 |
row-order-change | (dragStartKey: string, targetRowKey: string) | 行拖拽排序完成 |
col-resize | (col: StkTableColumn<DT>) | 列宽变化 |
toggle-row-expand | ({ expanded: boolean, row: DT, col: StkTableColumn<DT> | null }) | 行展开/收起 |
toggle-tree-expand | ({ expanded: boolean, row: DT, col: StkTableColumn<DT> | null }) | 树节点展开/收起 |
area-selection-change | (ranges: AreaSelectionRange[]) | 选区变化 |
filter-change | (status: Record<UniqKey, FilterStatus>) | 筛选变化(Beta) |
update:columns | (cols: StkTableColumn<DT>[]) | v-model:columns 更新 |
| 插槽名 | 作用域 | 说明 |
|---|---|---|
tableHeader | { col: StkTableColumn<DT> } | 自定义表头单元格 |
empty | 无 | 自定义空数据展示 |
expand | { row: DT, col: StkTableColumn<DT> } | 展开行内容 |
customBottom | 无 | 表格底部自定义区域 |
通过 ref 获取组件实例后调用:
const tableRef = ref<InstanceType<typeof StkTable>>();
| 方法 | 签名 | 说明 |
|---|---|---|
initVirtualScroll | () => void | 重算虚拟滚动宽高 |
initVirtualScrollX | () => void | 重算虚拟滚动宽度 |
initVirtualScrollY | (height?: number) => void | 重算虚拟滚动高度,可指定高度 |
setCurrentRow | (rowKeyOrRow: string | undefined | DT, option?: { silent?: boolean; deep?: boolean }) => void | 选中行 |
setSelectedCell | (row?: DT, col?: StkTableColumn<DT>, option?: { silent?: boolean }) => void | 选中单元格(cellActive=true) |
setHighlightDimCell | (rowKey: UniqKey, colKey: string, option?: HighlightDimCellOption) => void | 高亮闪烁单元格 |
setHighlightDimRow | (rowKeys: UniqKey[], option?: HighlightDimRowOption) => void | 高亮闪烁行 |
setSorter | (colKey: string, order: Order, option?: { append?: boolean; force?: boolean; silent?: boolean; sort?: boolean; sortOption?: SortOption<DT> }) => DT[] | 设排序,返回排序后数据。option.append=true 时多列排序追加 |
resetSorter | () => void | 重置排序 |
getSortColumns | () => { key: keyof DT | undefined, order: Order }[] | 获取排序信息 |
scrollTo | (top?: number | null, left?: number | null) => void | 滚动到位置(null=不变) |
getTableData | () => DT[] | 获取排序/过滤后数据 |
getRowIndex | (row: DT) => number | 获取行索引 |
getColumnIndex | (column: PrivateStkTableColumn<DT>) => number | 获取列索引 |
setRowExpand | (rowKeyOrRow: string | undefined | DT, expand?: boolean | null, data?: { col?: StkTableColumn<DT>; silent?: boolean }) => void | 设置行展开 |
setAutoHeight | (rowKey: UniqKey, height?: number | null) => void | 更新可变行高,传 null 则清除该行行高 |
clearAllAutoHeight | () => void | 清除所有行高缓存 |
setTreeExpand | (row: (UniqKey | DT) | (UniqKey | DT)[], option?: { expand?: boolean }) => void | 设置树节点展开 |
getSelectedArea | () => { rows: DT[], cols: StkTableColumn<DT>[], ranges: AreaSelectionRange[] } | null | 获取选区信息 |
setAreaSelection | (ranges?: AreaSelectionSetterRange<DT>, option?: { silent?: boolean; scrollToView?: boolean }) => AreaSelectionRange[] | 设置选区范围 |
clearSelectedArea | () => void | 清空选区 |
copySelectedArea | () => string | 复制选区到剪贴板,返回复制文本 |
setFilter | (status: Record<UniqKey, FilterStatus> | null, option?: { remote?: boolean }) => void | 设置筛选 |
sortCol | ComputedRef<keyof DT | undefined> | 当前排序列 dataIndex(属性) |
sortStates | Ref<SortState<DT>[]> | 排序状态数组(属性) |
type Order = null | 'asc' | 'desc';
type DefaultSortConfig<T> = {
key?: StkTableColumn<T>['key'];
dataIndex: StkTableColumn<T>['dataIndex'];
order: Order;
sortField?: StkTableColumn<T>['sortField'];
sortType?: StkTableColumn<T>['sortType'];
sorter?: StkTableColumn<T>['sorter'];
silent?: boolean;
};
type SortConfig<T> = {
defaultSort?: DefaultSortConfig<T>;
emptyToBottom?: boolean; // 默认 false
stringLocaleCompare?: boolean; // 默认 false
sortChildren?: boolean; // 默认 false
multiSort?: boolean; // 默认 false
multiSortLimit?: number; // 默认 3
};
type SortState<T> = {
key?: any;
dataIndex: keyof T & string;
sortField?: keyof T;
sortType?: 'number' | 'string';
order: Order;
};
type SortOption<T> = Pick<StkTableColumn<T>, 'sorter' | 'dataIndex' | 'sortField' | 'sortType'>;
type RowActiveOption<T> = {
enabled?: boolean;
disabled?: (row: T) => boolean;
revokable?: boolean;
};
type TreeConfig = {
defaultExpandAll?: boolean;
defaultExpandKeys?: (string | number)[];
defaultExpandLevel?: number;
};
type AreaSelectionConfig<T> = {
enabled?: boolean; // 默认 true(当 areaSelection 为 true 时)
formatCellForClipboard?: (row: T, col: StkTableColumn<T>, rawValue: any) => string;
keyboard?: boolean; // 默认 false
ctrl?: boolean; // 默认 true
shift?: boolean; // 默认 true
highlight?: {
cell?: boolean; // 默认 true
row?: boolean; // 默认 false
};
};
type AreaSelectionRange = {
index: {
x: [number, number]; // @deprecated
y: [number, number]; // @deprecated
begin: { row: number; col: number };
end: { row: number; col: number };
};
};
type AreaSelectionSetterRange<T> = {
begin: { row: number | T; col?: number | StkTableColumn<T> };
end?: { row: number | T; col?: number | StkTableColumn<T> };
};
type HeaderDragConfig<T> = {
mode?: 'none' | 'insert' | 'swap'; // 默认 'insert'
disabled?: (col: StkTableColumn<T>) => boolean;
};
type ColResizableConfig<T> = {
disabled: (col: StkTableColumn<T>) => boolean;
};
type DragRowConfig = {
mode?: 'none' | 'insert' | 'swap'; // 默认 'insert'
};
type AutoRowHeightConfig<T> = {
expectedHeight?: number | ((row: T) => number);
};
type ScrollbarOptions = {
enabled?: boolean;
width?: number; // 默认 8
height?: number; // 默认 8
minWidth?: number; // 默认 20
minHeight?: number; // 默认 20
};
type HighlightConfig = {
duration?: number; // 秒
fps?: number;
};
type HighlightDimCellOption = {
method?: 'animation' | 'css'; // 默认 'animation'
duration?: number;
className?: string; // method='css' 时使用
keyframe?: Keyframe[]; // method='animation' 时自定义关键帧
};
type HighlightDimRowOption = {
method?: 'animation' | 'css'; // 默认 'animation'
duration?: number;
className?: string; // method='css' 时使用
keyframe?: Keyframe[]; // method='animation' 时自定义关键帧
};
type SeqConfig = { startIndex?: number };
type ExpandConfig = { height?: number };
type FooterConfig = { position?: 'bottom' | 'top' };
type ExperimentalConfig = { scrollY?: boolean };
type UniqKey = string | number;
StkTable 提供三种自定义单元格渲染方式:
customCell - 自定义表体单元格customHeaderCell - 自定义表头单元格customFooterCell - 自定义表尾单元格注意:
CustomCellProps、CustomHeaderCellProps、CustomFooterCellProps类型未从stk-table-vue包导出,需自行定义或使用InstanceType推导。
// customCell props(组件内部传入)
type CustomCellProps<T> = {
row: T; // 当前行数据
col: StkTableColumn<T>; // 列配置
cellValue: any; // row[col.dataIndex] 的值
rowIndex: number; // 行索引
colIndex: number; // 列索引
expanded?: StkTableColumn<any>; // 展开行配置(未展开为null)
treeExpanded?: boolean; // 树节点是否展开
};
// customHeaderCell props
type CustomHeaderCellProps<T> = {
col: StkTableColumn<T>;
rowIndex: number;
colIndex: number;
};
// customFooterCell props
type CustomFooterCellProps<T> = {
col: StkTableColumn<T>;
row: T; // 表尾行数据
cellValue: any;
rowIndex: number;
colIndex: number;
};
适用于简单的单元格内容定制:
import { h } from 'vue';
import type { StkTableColumn } from 'stk-table-vue';
interface RowData {
name: string;
yield: number;
status: 'active' | 'inactive';
}
const columns: StkTableColumn<RowData>[] = [
// 基础格式化:添加单位
{
title: '收益率',
dataIndex: 'yield',
customCell: ({ cellValue }) => h('span', `${(cellValue * 100).toFixed(2)}%`),
},
// 条件样式
{
title: '状态',
dataIndex: 'status',
customCell: ({ cellValue }) => h('span', {
style: { color: cellValue === 'active' ? '#52c41a' : '#ff4d4f' }
}, cellValue === 'active' ? '启用' : '禁用'),
},
// 复杂内容
{
title: '名称',
dataIndex: 'name',
customCell: ({ row, cellValue }) => h('div', {
style: { display: 'flex', alignItems: 'center', gap: '8px' }
}, [
h('span', { class: 'avatar' }),
h('strong', cellValue),
]),
},
// 表头自定义
{
title: '操作',
dataIndex: 'action',
customHeaderCell: () => h('span', { style: { color: '#ff4d4f' } }, '⚠ 操作'),
},
// 表尾自定义
{
title: '数量',
dataIndex: 'count',
customFooterCell: ({ cellValue }) => h('strong', `合计: ${cellValue}`),
},
];
适用于复杂的单元格逻辑,支持完整的 Vue 组件能力:
::: 文件结构示例
columns/
├── index.ts # 列配置
├── YieldCell.vue # 收益率单元格组件
├── StatusCell.vue # 状态单元格组件
└── types.ts # 数据类型定义
:::
// columns/index.ts
import type { StkTableColumn } from 'stk-table-vue';
import type { RowData } from './types';
import YieldCell from './YieldCell.vue';
import StatusCell from './StatusCell.vue';
export const columns: StkTableColumn<RowData>[] = [
{ title: '代码', dataIndex: 'code' },
{ title: '收益率', dataIndex: 'yield', align: 'right', customCell: YieldCell },
{ title: '状态', dataIndex: 'status', customCell: StatusCell },
];
<!-- columns/YieldCell.vue -->
<script lang="ts" setup>
import { computed } from 'vue';
// 注意:CustomCellProps 未从包中导出,需自行定义 props
const props = defineProps<{
row: RowData;
col: any;
cellValue: any;
rowIndex: number;
colIndex: number;
}>();
const displayValue = computed(() => {
const val = props.cellValue * 100;
return val > 0 ? `+${val.toFixed(2)}%` : `${val.toFixed(2)}%`;
});
const colorClass = computed(() => {
if (props.cellValue > 0) return 'color-up';
if (props.cellValue < 0) return 'color-down';
return '';
});
</script>
<template>
<span :class="colorClass">{{ displayValue }}</span>
</template>
<style scoped>
.color-up { color: #52c41a; }
.color-down { color: #ff4d4f; }
</style>
适用于熟悉 JSX 语法的开发者:
import type { StkTableColumn } from 'stk-table-vue';
interface RowData {
name: string;
score: number;
}
const columns: StkTableColumn<RowData>[] = [
{
title: '姓名',
dataIndex: 'name',
customCell: ({ cellValue }) => (
<span style={{ color: '#1890ff' }}>{cellValue}</span>
),
},
{
title: '分数',
dataIndex: 'score',
customCell: ({ cellValue }) => {
const color = cellValue >= 90 ? '#52c41a' : cellValue >= 60 ? '#faad14' : '#ff4d4f';
return <span style={{ color, fontWeight: 'bold' }}>{cellValue}</span>;
},
},
];
快速创建可编辑单元格:
import { createEditableCell } from 'stk-table-vue';
import type { StkTableColumn } from 'stk-table-vue';
const { EditableCell } = createEditableCell({
trigger: 'dblclick', // 触发编辑的事件,默认 'dblclick',可选 'click'
onChange: (newValue, row, dataIndex) => {
console.log(`行 ${row.id} 的 ${dataIndex} 变更为 ${newValue}`);
},
});
const columns: StkTableColumn<RowData>[] = [
{ title: '名称', dataIndex: 'name', customCell: EditableCell },
{ title: '年龄', dataIndex: 'age', customCell: EditableCell },
];
建议包裹元素:customCell 返回的 VNode 建议用元素(div/span 等)包裹,否则 TextNode 作为 <td> 子节点可能导致布局问题。
谨慎使用行内元素:customCell 的根元素请谨慎设置为 inline/inline-block/inline-flex 等行内元素,此布局在虚拟列表中可能会撑开行高。
组件类型兼容:customCell 类型直接定义 Component<Props> 时,如果 Props 属性为必选,则通过 defineComponent 创建的组件必须要定义所有的 Prop。建议将所有 Props 定义为可选,或使用函数式组件。
选区复制格式化:如果使用了 customCell 自定义渲染,应该配合 areaSelection.formatCellForClipboard 回调以确保复制内容与展示内容一致。
<template>
<div style="height: 500px">
<StkTable
virtual
row-key="id"
:row-height="36"
:columns="columns"
:data-source="dataSource"
/>
</div>
</template>
注意:虚拟滚动需要容器具有确定高度(通过父容器固定高度或组件自身 CSS 均可)。
<StkTable virtual virtual-x row-key="id" :columns="columns" :data-source="dataSource" />
横向虚拟滚动要求所有列必须设置
width。
<template>
<StkTable
row-key="id"
:columns="columns"
:data-source="dataSource"
@sort-change="onSortChange"
/>
</template>
<script setup>
const columns = [
{ title: '名称', dataIndex: 'name', sorter: true, sortType: 'string' },
{ title: '年龄', dataIndex: 'age', sorter: true, sortType: 'number' },
];
function onSortChange(col, order, sortedData, config) {
console.log(`按 ${col?.dataIndex} ${order} 排序`);
}
</script>
<StkTable
ref="tableRef"
:sort-config="{ multiSort: true, multiSortLimit: 3 }"
:columns="columns"
:data-source="dataSource"
/>
// 编程式设置多列排序
tableRef.value?.setSorter('department', 'asc');
tableRef.value?.setSorter('age', 'desc', { append: true });
<StkTable fixed-col-shadow :columns="columns" :data-source="dataSource" />
const columns = [
{ title: 'ID', dataIndex: 'id', fixed: 'left', width: 80 },
{ title: '名称', dataIndex: 'name', width: 200 },
// ... 更多列
{ title: '操作', dataIndex: 'action', fixed: 'right', width: 120 },
];
import { h } from 'vue';
const columns = [
{
title: '状态',
dataIndex: 'status',
customCell: ({ row, cellValue }) => {
return h('span', {
style: { color: cellValue === 'active' ? 'green' : 'red' },
}, cellValue);
},
},
{
title: '操作',
dataIndex: 'action',
customCell: ({ row }) => {
return h('div', [
h('button', { onClick: () => handleEdit(row) }, '编辑'),
h('button', { onClick: () => handleDelete(row) }, '删除'),
]);
},
},
];
<StkTable
row-key="id"
:columns="columns"
:data-source="treeData"
:tree-config="{ defaultExpandLevel: 1 }"
@toggle-tree-expand="onToggle"
/>
const columns = [
{ type: 'tree-node', title: '名称', dataIndex: 'name' },
{ title: '值', dataIndex: 'value' },
];
// 数据中用 children 字段表示子节点
const treeData = [
{ id: 1, name: '节点1', value: 100, children: [
{ id: 11, name: '子节点1-1', value: 50 },
]},
];
<StkTable row-key="id" :columns="columns" :data-source="dataSource">
<template #expand="{ row }">
<div style="padding: 10px">详情:{{ row.detail }}</div>
</template>
</StkTable>
const columns = [
{ type: 'expand', dataIndex: '', width: 50 },
{ title: '名称', dataIndex: 'name' },
];
<StkTable
row-key="id"
:columns="columns"
:data-source="dataSource"
:drag-row-config="{ mode: 'insert' }"
@row-order-change="onRowDrag"
/>
const columns = [
{ type: 'dragRow', dataIndex: '', width: 60, title: '拖拽' },
{ title: '名称', dataIndex: 'name' },
];
<StkTable
v-model:columns="columns"
header-drag
row-key="id"
:data-source="dataSource"
/>
<StkTable
v-model:columns="columns"
col-resizable
row-key="id"
:data-source="dataSource"
/>
列宽拖拽要求每列都设置
width。
<StkTable
ref="tableRef"
row-key="id"
:highlight-config="{ duration: 2, fps: 0 }"
:columns="columns"
:data-source="dataSource"
/>
// 高亮单元格(支持第三个参数 option 自定义动画方式)
tableRef.value?.setHighlightDimCell('row-key-1', 'age');
// 高亮行(支持第二个参数 option 自定义动画方式)
tableRef.value?.setHighlightDimRow(['row-key-1', 'row-key-2']);
<template>
<StkTable
row-key="id"
:row-active="{ enabled: true, revokable: true, disabled: row => row.locked }"
:columns="columns"
:data-source="dataSource"
@current-change="onCurrentChange"
/>
</template>
<script setup>
const columns = [
{ title: 'ID', dataIndex: 'id' },
{ title: '名称', dataIndex: 'name' },
{ title: '状态', dataIndex: 'status' },
];
const dataSource = [
{ id: 1, name: '张三', status: 'active' },
{ id: 2, name: '李四', status: 'locked', locked: true }, // 此行不能被点击选中
];
function onCurrentChange(event, row, { select }) {
console.log('当前行:', row);
console.log('选中状态:', select); // true=选中, false=取消选中
}
</script>
提示:
rowActive设为false仅隐藏内部样式,tr上仍会添加active类,方便自定义样式。rowActive.disabled禁用的行仍可通过setCurrentRow()方法选中。revokable: true表示再次点击当前行可以取消选中。
注意:Area Selection 是按需注册的特性,需先调用
registerFeature(useAreaSelection)才能使用。
<StkTable
row-key="id"
:area-selection="{ enabled: true, keyboard: true }"
:columns="columns"
:data-source="dataSource"
@area-selection-change="onSelection"
/>
<StkTable
row-key="id"
:area-selection="{
enabled: true,
keyboard: true,
ctrl: true,
shift: true,
formatCellForClipboard: (row, col, rawValue) => {
if (col.dataIndex === 'status') {
return rawValue === 1 ? '正常' : '异常';
}
return String(rawValue);
},
highlight: {
cell: true,
row: false,
}
}"
:columns="columns"
:data-source="dataSource"
/>
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
enabled | boolean | false | 是否启用区域选择 |
keyboard | boolean | false | 是否启用键盘导航(方向键/Tab/Shift+Tab) |
ctrl | boolean | true | 是否启用 Ctrl/Cmd 多选不连续区域 |
shift | boolean | true | 是否启用 Shift 扩选功能 |
formatCellForClipboard | Function | undefined | 复制到剪贴板时的格式化回调 |
highlight.cell | boolean | true | 是否启用单元格高亮与选中边框 |
highlight.row | boolean | false | 是否启用整行高亮 |
const columns = [
{ type: 'seq', title: '#', dataIndex: '', width: 50 },
// ...其他列
];
<StkTable
:columns="columns"
:data-source="dataSource"
:footer-data="[{ name: '合计', amount: 10000 }]"
:footer-config="{ position: 'bottom' }"
/>
const columns = [
{
title: '基本信息',
dataIndex: '',
children: [
{ title: '名称', dataIndex: 'name', width: 100 },
{ title: '年龄', dataIndex: 'age', width: 80 },
],
},
{ title: '备注', dataIndex: 'remark' },
];
const columns = [
{
title: '部门',
dataIndex: 'dept',
mergeCells: ({ row, rowIndex }) => {
if (rowIndex === 0) return { rowspan: 2, colspan: 1 };
if (rowIndex === 1) return { rowspan: 0 }; // 被合并,设为0隐藏
},
},
];
<StkTable theme="dark" :columns="columns" :data-source="dataSource" />
<StkTable :columns="columns" :data-source="[]">
<template #empty>
<div class="my-empty">暂无数据,请添加</div>
</template>
</StkTable>
<StkTable
sort-remote
:columns="columns"
:data-source="dataSource"
@sort-change="onSortChange"
/>
async function onSortChange(col, order) {
const res = await fetch(`/api/data?sort=${col.dataIndex}&order=${order}`);
dataSource.value = await res.json();
}
StkTable 支持通过 CSS 变量自定义表格的样式外观:
<template>
<div class="my-table-container">
<StkTable
row-key="id"
:columns="columns"
:data-source="dataSource"
/>
</div>
</template>
<style>
.my-table-container {
--border-color: #e0e0e0;
--border-width: 1px;
--td-bgc: #ffffff;
--td-hover-color: #f5f5f5;
--td-active-color: #e3f2fd;
--th-bgc: #fafafa;
--tf-bgc: #f5f5f5;
--th-color: #333333;
--tr-hover-bgc: #f5f5f5;
--tr-active-bgc: #e3f2fd;
--stripe-bgc: #fafafa;
--sort-arrow-color: #999999;
--sort-arrow-hover-color: #666666;
--sort-arrow-active-color: #1890ff;
--sort-arrow-active-sub-color: #cccccc;
--fold-icon-color: #999999;
--fold-icon-hover-color: #666666;
--col-resize-indicator-color: #1890ff;
--fixed-col-shadow-color-from: rgba(0, 0, 0, 0.1);
--fixed-col-shadow-color-to: rgba(0, 0, 0, 0);
--drag-handle-hover-color: #d9d9d9;
--sb-thumb-color: #c1c1c1;
--sb-thumb-hover-color: #a8a8a8;
--cs-bgc: #d3eafd;
--cs-bc: #2196f3;
}
</style>
注意:行高(
rowHeight、headerRowHeight、footerRowHeight)等尺寸相关配置请使用组件的 Props,不要通过 CSS 变量来修改。
virtualX)建议为所有列设置 width,未设置时默认列宽为 100。colResizable)和表头拖拽(headerDrag)需要配合 v-model:columns 使用。rowKey 强烈建议设置,大多数功能依赖行唯一标识。customCell 使用 Vue 的 h() 函数返回 VNode,不是 JSX/模板(除非在 JSX 文件中)。sorter: true,并推荐设置 sortType: 'number' | 'string'。fixed)建议配合设置 width。children。theme="dark",组件内置了暗色样式。expandConfig.height 指定展开区域高度。registerFeature(useAreaSelection) 后再使用 areaSelection prop。CustomCellProps 等类型未从包导出,SFC 组件中需自行定义 props 或使用泛型推导。