---
title: "Descriptions 描述列表"
description: "按列排布的只读标签与值列表"
category: Data
status: beta
since: 0.6.3
tags: [descriptions, data, detail, key-value, record]
syncStatus: reviewed
verified: true
---

## 安装

:::TuffCodeBlock{lang="bash"}
---
code: |
  pnpm add @talex-touch/tuffex
---
:::

:::TuffCodeBlock{lang="typescript"}
---
code: |
  import { TxDescriptions, TxDescriptionsItem } from '@talex-touch/tuffex/descriptions'
  // 两个组件共用一份样式
  import '@talex-touch/tuffex/descriptions/style.css'
  import '@talex-touch/tuffex/base.css' // token 与重置样式，全局引入一次
---
:::

## 用法

### 基础
默认两列；空值显示 `emptyText`，`0` 照常显示。
:::TuffDemoWrapper{demo="DescriptionsBasicDemo" code-lang="vue"}
---
code: |
  <template>
    <TxDescriptions>
      <TxDescriptionsItem label="姓名">{{ user.name }}</TxDescriptionsItem>
      <TxDescriptionsItem label="邮箱">{{ user.email }}</TxDescriptionsItem>
      <TxDescriptionsItem label="套餐">
        <TxStatusBadge status="success" :text="user.plan" size="sm" />
      </TxDescriptionsItem>
      <TxDescriptionsItem label="剩余积分">{{ user.credits }}</TxDescriptionsItem>
      <!-- 没有手机号：值显示 emptyText -->
      <TxDescriptionsItem label="手机">{{ user.phone }}</TxDescriptionsItem>
      <TxDescriptionsItem label="最近登录">{{ user.lastSignIn }}</TxDescriptionsItem>
      <TxDescriptionsItem label="用户 ID" :span="2">
        <code>{{ user.id }}</code>
      </TxDescriptionsItem>
    </TxDescriptions>
  </template>
---
:::

### 布局与尺寸
`layout` 决定标签在值旁边还是上方；`size="sm"` 用于抽屉和侧边面板。
:::TuffDemoWrapper{demo="DescriptionsLayoutDemo" code-lang="vue"}
---
code: |
  <script setup lang="ts">
  import { ref } from 'vue'

  const layout = ref<'horizontal' | 'vertical'>('horizontal')
  const size = ref<'sm' | 'md'>('md')
  </script>

  <template>
    <TxDescriptions :layout="layout" :size="size" :columns="3">
      <TxDescriptionsItem v-for="field in fields" :key="field.label" :label="field.label">
        {{ field.value }}
      </TxDescriptionsItem>
    </TxDescriptions>
  </template>
---
:::

### 列数与跨列
`span` 让长字段跨列，最多到 `columns`；容器窄于 480px 时退为单列。
:::TuffDemoWrapper{demo="DescriptionsColumnsDemo" code-lang="vue"}
---
code: |
  <template>
    <TxDescriptions :columns="3">
      <TxDescriptionsItem label="订单号">TU-2408</TxDescriptionsItem>
      <TxDescriptionsItem label="状态">
        <TxStatusBadge status="success" text="已支付" size="sm" />
      </TxDescriptionsItem>
      <TxDescriptionsItem label="金额">¥12,800</TxDescriptionsItem>
      <TxDescriptionsItem label="客户">林晓</TxDescriptionsItem>
      <TxDescriptionsItem label="收货地址" :span="2">
        上海市徐汇区漕溪北路 88 号 12 楼
      </TxDescriptionsItem>
      <TxDescriptionsItem label="备注" :span="3">
        客户要求电子发票，开票抬头与付款主体一致。
      </TxDescriptionsItem>
    </TxDescriptions>
  </template>
---
:::

### 最佳实践

- 缺失的值留空，不手写 `—`；需要别的占位时传一次 `emptyText`。
- 长字段（ID、地址、备注）用 `span` 加宽，不为它调小整张列表的 `columns`。
- 标签保持简短；上下堆叠的几张列表需要对齐时设置 `labelWidth`。
- 条目直接放进默认插槽（`v-for`、`v-if` 均可），不要外包元素。
- 由父元素给列表宽度：flex 行中给 `flex: 1`；按内容收缩的父元素会让它塌成零宽。

## API 参考

### TxDescriptions

#### 属性

| 名称 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `columns` | `number` | `2` | 每行项数，向下取整，最小为 1。 |
| `layout` | `'horizontal' \| 'vertical'` | `'horizontal'` | `horizontal` 标签在值旁、同列共用标签轨道；`vertical` 标签在值上方。 |
| `size` | `'sm' \| 'md'` | `'md'` | `md` 值 14px、标签 13px；`sm` 均为 13px，间距更紧。 |
| `emptyText` | `string` | `'—'` | 值不渲染任何内容时的占位；`0` 算作值。 |
| `labelWidth` | `string \| number` | - | 水平布局的标签宽度，数字按 px；缺省取最长标签，至多 40%。 |

#### 插槽

| 插槽 | 说明 |
|------|------|
| `default` | 直接放 `TxDescriptionsItem`；外包元素会破坏 `<dl>` 与网格。 |

### TxDescriptionsItem

#### 属性

| 名称 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `label` | `string` | `''` | 标签文字；`label` 插槽可替换。 |
| `span` | `number` | `1` | 跨越的列数，限制在 1 到 `columns` 之间。 |

#### 插槽

| 插槽 | 说明 |
|------|------|
| `default` | 值；不渲染内容时显示 `emptyText`。 |
| `label` | 替换标签文字，仍在同一个 `<dt>` 里。 |

### CSS 变量

| 变量 | 默认值 | 说明 |
|------|--------|------|
| `--tx-descriptions-gap` | `12px`；`sm` 为 `8px` | 行间距及水平布局中标签与值的间距；两项之间为其两倍。 |
| `--tx-descriptions-font-size` | `14px`；`sm` 为 `13px` | 值的字号；标签小 1px，但不小于 13px。 |
| `--tx-descriptions-label-width` | 未设置 | 标签轨道宽度；`labelWidth` 写在根节点上，宿主也可在祖先上设置。 |

- `sm` 以单个类的权重设置前两个变量，权重更高的宿主规则（如 scoped 类）可覆盖。
- `--tx-descriptions-columns` 与 `--tx-descriptions-span` 由组件写入，宿主无需设置。

### 类型

:::TuffCodeBlock{lang="typescript"}
---
code: |
  type DescriptionsLayout = 'horizontal' | 'vertical'
  type DescriptionsSize = 'sm' | 'md'
---
:::

## 概述

- 每一项是 `<dl>` 中的 `div` 分组，含一个 `dt` 和一个 `dd`，辅助技术读作术语与描述。
- 水平布局中，同列标签共用一条轨道，宽度取最长标签、至多 40%，超出时换行；值与标签首行基线对齐。
- 各项按源码顺序填充；放不进当前行剩余空间的项另起一行，空位留白。
- 自身宽度（容器查询，非视口）小于 480px 时为单列，每项占满整行。
- 插槽只渲染注释或空白时算空（含 `{{ null }}`、`v-if` 为假、空 `v-for`），显示 `emptyText`；`0` 与任何元素都算内容。
- 值可在任意位置换行，过长的 ID、邮箱、URL 不会撑宽列。

## 技术实现

- 标签对齐靠 CSS `subgrid`；单列回退靠根节点上的 `@container (width < 480px)`，所以列表是根节点内的独立元素。
- 源码：`packages/tuffex/packages/components/src/descriptions/`。

<TuffDocSourceLink />

## 使用场景

- 抽屉或详情面板里展示一条记录：成员、订阅、一次运行、一个插件。
- 表单或表格上方的摘要，说明接下来操作的对象。
- 卡片里的只读设置与元数据。

## 相关组件

- [DataTable 数据表格](./data-table.zh.mdc)：字段相同的多条记录。
- [Form 表单](./form.zh.mdc)：可编辑的对应物，一行一个标签和输入框。
- [Drawer 抽屉](./drawer.zh.mdc)：展示单条记录详情的常见容器。
