基础用法
| 名称 | 体积 | 更新时间 | |
|---|---|---|---|
| 组件库 | 51 | 1.2 MB | 2026-09-14 |
| 文档站 | 8 | 320 KB | 2026-09-12 |
| 演示页 | 120 | 890 KB | 2026-09-10 |
| 测试用例 | 83 | — | 2026-09-14 |
vue
<script setup>
import { ref } from 'vue'
const rows = ref([
{ name: '组件库', count: 51, size: '1.2 MB' },
{ name: '文档站', count: 8, size: '320 KB' }
])
const columns = [
{ key: 'name', title: '名称' },
{ key: 'count', title: '数量', sortable: true, align: 'right' },
{ key: 'size', title: '体积', align: 'right' }
]
</script>
<template>
<SrTable :data="rows" :columns="columns" />
</template>表格是数据驱动的,没有 SrTableColumn
这里最容易踩坑
SrTable 没有子组件。列由 columns 数组定义,而不是写成 <SrTableColumn> 标签。
vue
<!-- ❌ 这样写,Vue 会把它当成未注册的原生标签 -->
<SrTable :data="rows">
<SrTableColumn prop="name" label="名称" />
</SrTable>
<!-- ✅ 正确 -->
<SrTable :data="rows" :columns="columns" />写错的后果很隐蔽:页面照常渲染,只是所有单元格都是空的, 控制台只有一条 Failed to resolve component 警告。
SrTableColumn 这个名字确实存在,但它是 types.ts 里的类型,不是组件。
列配置
| 字段 | 类型 | 说明 |
|---|---|---|
key | string | 取值字段名,支持 a.b 嵌套路径 |
title | string | 列标题 |
width | string | 列宽('120px' / '20%') |
minWidth | string | 内容挤压时的下限 |
align | 'left' | 'center' | 'right' | 对齐方式 |
sortable | boolean | 是否可排序 |
fixed | 'left' | 'right' | 固定列 |
render | (row) => string | 自定义单元格文本 |
排序
点表头切换升序 / 降序 / 无排序(三态循环)。
| 名称 | 体积 | 更新时间 | |
|---|---|---|---|
| 文档站 | 8 | 320 KB | 2026-09-12 |
| 组件库 | 51 | 1.2 MB | 2026-09-14 |
| 测试用例 | 83 | — | 2026-09-14 |
| 演示页 | 120 | 890 KB | 2026-09-10 |
vue
<SrTable :data="rows" :columns="columns" default-sort-key="count" default-sort-order="asc" />数字按数值比较,不是字典序
normalizeValue 会判断字段类型:两个都是数字时走数值比较, 其余情况降级为字符串比较。
统一转字符串会让 10 排在 9 前面——这是表格排序最常见的错误。 点上面「数量」列头验证:结果应该是 8 → 51 → 83 → 120, 而不是字典序的 120 → 51 → 83 → 8。
排序是在组件内部对传入数据做副本排序,不会改动 props.data。
ts
// 组件内部:复制后再排
return [...props.data].sort(...)直接 sort() 会就地修改数组——宿主的数据也会跟着变, 这类 bug 极难追查(数据「自己」变了)。
固定列与横向滚动
fixed 用 position: sticky 实现。左侧固定列须在列序最前, 右侧固定列须在最后。
| 名称 | 体积 | 更新时间 | 操作 | |
|---|---|---|---|---|
| 组件库 | 51 | 1.2 MB | 2026-09-14 | |
| 文档站 | 8 | 320 KB | 2026-09-12 | |
| 演示页 | 120 | 890 KB | 2026-09-10 | |
| 测试用例 | 83 | — | 2026-09-14 |
vue
const columns = [
{ key: 'name', title: '名称', width: '160px', fixed: 'left' },
{ key: 'count', title: '数量', width: '200px' },
{ key: 'updated', title: '更新时间', width: '200px' },
{ key: 'action', title: '操作', width: '120px', fixed: 'right' }
]固定列需要显式宽度
sticky 的偏移量靠累计前面各列的宽度算出。 没有宽度的列会被内容撑开,累计值随之失准,固定列的位置就会错。
给所有固定列、以及它们前面的每一列都写上 width。
吸顶表头
sticky-header 配合 max-height,滚动时表头保持可见。
| 名称 | 体积 | 更新时间 | |
|---|---|---|---|
| 组件库 | 51 | 1.2 MB | 2026-09-14 |
| 文档站 | 8 | 320 KB | 2026-09-12 |
| 演示页 | 120 | 890 KB | 2026-09-10 |
| 测试用例 | 83 | — | 2026-09-14 |
vue
<SrTable :data="rows" :columns="columns" sticky-header max-height="160px" />条纹、描边与悬停
| 名称 | 体积 | 更新时间 | |
|---|---|---|---|
| 组件库 | 51 | 1.2 MB | 2026-09-14 |
| 文档站 | 8 | 320 KB | 2026-09-12 |
| 演示页 | 120 | 890 KB | 2026-09-10 |
| 测试用例 | 83 | — | 2026-09-14 |
vue
<SrTable :data="rows" :columns="columns" striped bordered highlight-hover />空态与加载
loading 时显示骨架行,行数由 loadingRows 控制—— 骨架的宽度应该与实际内容接近,否则数据到位时会有明显的跳动。
| 名称 | 体积 | 更新时间 | |
|---|---|---|---|
还没有数据 | |||
| 名称 | 体积 | 更新时间 | |
|---|---|---|---|
vue
<SrTable :data="[]" :columns="columns" empty-text="还没有数据" />
<SrTable :data="[]" :columns="columns" loading :loading-rows="3" />尺寸
| 名称 | 体积 | 更新时间 | |
|---|---|---|---|
| 组件库 | 51 | 1.2 MB | 2026-09-14 |
| 文档站 | 8 | 320 KB | 2026-09-12 |
vue
<SrTable size="sm" :data="rows" :columns="columns" />
<SrTable size="md" :data="rows" :columns="columns" />Props
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
data | Record<string, any>[] | [] | 表格数据 |
columns | SrTableColumn[] | [] | 列配置 |
rowKey | string | — | 行唯一标识字段,用于 v-for 的 key |
striped | boolean | false | 斑马纹 |
bordered | boolean | false | 是否显示描边 |
highlightHover | boolean | true | 悬停高亮行 |
size | 'sm' | 'md' | 'lg' | 'md' | 尺寸 |
emptyText | string | — | 空态文案 |
loading | boolean | false | 是否显示骨架 |
loadingRows | number | 5 | 骨架行数 |
stickyHeader | boolean | false | 表头吸顶 |
maxHeight | string | — | 最大高度,配合 stickyHeader 使用 |
defaultSortKey | string | — | 初始排序列 |
defaultSortOrder | 'asc' | 'desc' | — | 初始排序方向 |
事件
| 事件 | 参数 | 说明 |
|---|---|---|
sort-change | { key, order } | 排序变化,order 为 'asc' / 'desc' / null |
无障碍
- 语义化标签:
<table>/<thead>/<tbody>/<th>,读屏软件能按表格朗读 - 可排序列的
<th>带aria-sort(ascending/descending/none), 这是唯一能让读屏用户知道当前排序状态的方式 - 骨架屏带
aria-busy="true",避免有辅助技术把占位内容当成真实数据