shadcn-svelte Table 组件详解:从基础响应式表格到 Data Table 实战
【免费下载链接】shadcn-svelteshadcn/ui, but for Svelte. ✨项目地址: https://gitcode.com/GitHub_Trending/sh/shadcn-svelte
shadcn-svelte 是 shadcn/ui 在 Svelte 生态的官方移植版本,其 Table 组件是一套基于原生 HTML<table>语义、开箱即用的响应式表格组件。本文以仓库内 docs/content/components/table.md 为核心,结合组件源码与示例,系统讲解其安装方式、9 个组成部件、样式原理,以及如何搭配 @tanstack/table 构建带排序、筛选与分页的完整 Data Table,让你读完即可在真实项目中落地使用。
组件概览:Table 组件解决什么问题
Table 组件(docs/content/components/table.md中描述为 "A responsive table component")的核心价值在于:它不重新发明表格逻辑,而是基于标准的<table>语义标签,通过一套预先打磨好的 Tailwind 样式和 Svelte 5 runes 语法封装,让开发者获得一个开箱即用、样式统一、可响应式滚动的表格基础层。
从源码结构看(docs/src/lib/registry/ui/table/index.ts),该组件由 9 个独立 Svelte 部件构成,全部通过命名空间导出方式对外提供:
| 导出名 | 底层元素 | 对应源文件 |
|---|---|---|
Table.Root | <table>(外包一层滚动容器 div) | table.svelte |
Table.Header | <thead> | table-header.svelte |
Table.Body | <tbody> | table-body.svelte |
Table.Footer | <tfoot> | table-footer.svelte |
Table.Row | <tr> | table-row.svelte |
Table.Head | <th> | table-head.svelte |
Table.Cell | <td> | table-cell.svelte |
Table.Caption | <caption> | table-caption.svelte |
Table.Row(同前) | — | — |
从 index.ts 可以看到每个部件既有短名(如Root、Head)也有带前缀的长名(如TableRoot、TableHead),两种命名均可使用,Table.Root这种命名空间写法是官方示例中的首选。
安装方式:CLI 一键添加与手动复制
原文档提供了两种安装路径,官方强烈推荐使用 CLI 方式,它会自动处理依赖解析与文件写入。
方式一:shadcn-svelte CLI(推荐)
在项目根目录直接执行:
npx shadcn-svelte@latest add table该命令会从注册表拉取 Table 组件及其依赖,自动写入到项目的$lib/components/ui/table目录,并同步更新项目的 CSS 变量与依赖清单。这一交互流程的底层逻辑对应仓库 packages/cli/src/commands/add 目录中的命令实现。
方式二:手动复制
如果你的项目需要定制或暂时无法使用 CLI,也可以手动操作:
- 从 docs/src/lib/registry/ui/table 目录复制全部 9 个
.svelte文件与index.ts到项目中的$lib/components/ui/table/目录; - 确保项目中已安装 bits-ui);
- 确认项目的全局 CSS 中已包含下文中描述的
.cn-table-*样式规则(可通过 CLI 的init自动注入,或手动从 docs/src/lib/registry/styles 下的风格文件同步)。
注意:组件源码内部统一使用
$lib别名导入cn与WithElementRef类型,手动复制时需保证项目的 tsconfig/svelte.config 已配置该别名(仓库根目录的 svelte.config.js 与 tsconfig.json 中有现成配置可参考)。
基础用法:发票列表示例逐步拆解
第一步:引入组件
在.svelte文件的<script>中引入整个命名空间:
<script lang="ts"> import * as Table from "$lib/components/ui/table/index.js"; </script>第二步:组织表格结构
<Table.Root> <Table.Caption>A list of your recent invoices.</Table.Caption> <Table.Header> <Table.Row> <Table.Head class="w-[100px]">Invoice</Table.Head> <Table.Head>Status</Table.Head> <Table.Head>Method</Table.Head> <Table.Head class="text-end">Amount</Table.Head> </Table.Row> </Table.Header> <Table.Body> <Table.Row> <Table.Cell class="font-medium">INV001</Table.Cell> <Table.Cell>Paid</Table.Cell> <Table.Cell>Credit Card</Table.Cell> <Table.Cell class="text-end">$250.00</Table.Cell> </Table.Row> </Table.Body> </Table.Root>第三步:结合数据渲染真实列表
仓库中的官方示例 table-demo.svelte 演示了如何用{#each}循环渲染真实业务数据,并额外展示了Table.Footer汇总行的写法:
<script lang="ts"> import * as Table from "$lib/registry/ui/table/index.js"; const invoices = [ { invoice: "INV001", paymentStatus: "Paid", totalAmount: "$250.00", paymentMethod: "Credit Card" }, // ... 更多行 ]; </script> <Table.Root> <Table.Caption>A list of your recent invoices.</Table.Caption> <Table.Header> <Table.Row> <Table.Head class="w-[100px]">Invoice</Table.Head> <Table.Head>Status</Table.Head> <Table.Head>Method</Table.Head> <Table.Head class="text-end">Amount</Table.Head> </Table.Row> </Table.Header> <Table.Body> {#each invoices as invoice (invoice)} <Table.Row> <Table.Cell class="font-medium">{invoice.invoice}</Table.Cell> <Table.Cell>{invoice.paymentStatus}</Table.Cell> <Table.Cell>{invoice.paymentMethod}</Table.Cell> <Table.Cell class="text-end">{invoice.totalAmount}</Table.Cell> </Table.Row> {/each} </Table.Body> <Table.Footer> <Table.Row> <Table.Cell colspan={3}>Total</Table.Cell> <Table.Cell class="text-end">$2,500.00</Table.Cell> </Table.Row> </Table.Footer> </Table.Root>关键点:
- 每个部件都接收
class属性并透传给底层原生元素,因此可以用 Tailwind 任意值做列宽、对齐等微调,例如class="w-[100px]"固定列宽、class="text-end"右对齐、class="font-medium"加粗; Table.Cell上可直接使用colspan等原生td属性;{#each}的 key 参数(示例中的(invoice))有助于 Svelte 高效复用与更新 DOM。
响应式原理:从源码看 Table 的样式设计
Table 组件之所以"响应式",关键在于Table.Root的源码结构。查看 table.svelte:
<div>.cn-table-container { @apply relative w-full overflow-x-auto; } .cn-table { @apply w-full caption-bottom text-sm; } .cn-table-header { @apply [&_tr]:border-b; } .cn-table-body { @apply [&_tr:last-child]:border-0; } .cn-table-footer { @apply border-t bg-muted/50 font-medium [&>tr]:last:border-b-0; } .cn-table-row { @apply border-b transition-colors hover:bg-muted/50><script lang="ts"> import { cn, type WithElementRef } from "$lib/utils.js"; import type { HTMLThAttributes } from "svelte/elements"; let { ref = $bindable(null), class: className, children, ...restProps }: WithElementRef<HTMLThAttributes> = $props(); </script> <th bind:this={ref} contenteditable="false">【免费下载链接】shadcn-svelteshadcn/ui, but for Svelte. ✨
项目地址: https://gitcode.com/GitHub_Trending/sh/shadcn-svelte创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考