원클릭으로
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 或使用泛型推导。