Skip to content

描述列表 Descriptions

赞助

成组展示多个只读字段

何时使用

  • 常见于详情页的信息展示

基本

Show Code
vue
<template>
  <Descriptions title="User Info">
    <template #extra>
      <a href="#" @click="onClick">more</a>
    </template>
    <DescriptionsItem label="UserName">Zhou Maomao</DescriptionsItem>
    <DescriptionsItem label="Telephone">1810000000</DescriptionsItem>
    <DescriptionsItem label="Live">Hangzhou, Zhejiang</DescriptionsItem>
    <DescriptionsItem label="Remark">empty</DescriptionsItem>
    <DescriptionsItem label="Address"
      >No. 18, Wantang Road, Xihu District, Hangzhou, Zhejiang, China</DescriptionsItem
    >
  </Descriptions>
</template>

带边框的

Show Code
vue
<template>
  <Descriptions title="User Info" bordered>
    <DescriptionsItem label="Product">Cloud Database</DescriptionsItem>
    <DescriptionsItem label="Billing Mode">Prepaid</DescriptionsItem>
    <DescriptionsItem label="Automatic Renewal">YES</DescriptionsItem>
    <DescriptionsItem label="Order time">2018-04-24 18:00:00</DescriptionsItem>
    <DescriptionsItem label="Usage Time" :span="2">2030-10-10 18:00:00</DescriptionsItem>
    <DescriptionsItem label="Status" :span="3">
      <Badge status="processing" ripple text="Running" />
    </DescriptionsItem>
    <DescriptionsItem label="Negotiated Amount">$80.00</DescriptionsItem>
    <DescriptionsItem label="Discount">$20.00</DescriptionsItem>
    <DescriptionsItem label="Official Receipts">$60.00</DescriptionsItem>
    <DescriptionsItem label="Config Info">
      Data disk type: MongoDB
      <br />
      Database version: 3.4
      <br />
      Package: dds.mongo.mid
      <br />
      Storage space: 10 GB
      <br />
      Replication factor: 3
      <br />
      Region: East China 1
      <br />
    </DescriptionsItem>
  </Descriptions>
</template>

自定义尺寸

Show Code
vue
<script setup lang="ts">
import { ref } from 'vue'
const size = ref('default')
const options = [
  {
    label: 'default',
    value: 'default'
  },
  {
    label: 'middle',
    value: 'middle'
  },
  {
    label: 'small',
    value: 'small'
  }
]
</script>
<template>
  <Flex vertical gap="middle">
    <Radio :options="options" v-model:value="size" button button-style="solid" />
    <Descriptions bordered title="Custom Size" :size="size">
      <template #extra>
        <Button type="primary">Edit</Button>
      </template>
      <DescriptionsItem label="Product">Cloud Database</DescriptionsItem>
      <DescriptionsItem label="Billing">Prepaid</DescriptionsItem>
      <DescriptionsItem label="Time">18:00:00</DescriptionsItem>
      <DescriptionsItem label="Amount">$80.00</DescriptionsItem>
      <DescriptionsItem label="Discount">$20.00</DescriptionsItem>
      <DescriptionsItem label="Official">$60.00</DescriptionsItem>
      <DescriptionsItem label="Config Info">
        Data disk type: MongoDB
        <br />
        Database version: 3.4
        <br />
        Package: dds.mongo.mid
        <br />
        Storage space: 10 GB
        <br />
        Replication factor: 3
        <br />
        Region: East China 1
        <br />
      </DescriptionsItem>
    </Descriptions>
    <Descriptions title="Custom Size" :size="size">
      <template #extra>
        <Button type="primary">Edit</Button>
      </template>
      <DescriptionsItem label="Product">Cloud Database</DescriptionsItem>
      <DescriptionsItem label="Billing">Prepaid</DescriptionsItem>
      <DescriptionsItem label="Time">18:00:00</DescriptionsItem>
      <DescriptionsItem label="Amount">$80.00</DescriptionsItem>
      <DescriptionsItem label="Discount">$20.00</DescriptionsItem>
      <DescriptionsItem label="Official">$60.00</DescriptionsItem>
    </Descriptions>
  </Flex>
</template>

响应式

Show Code
vue
<template>
  <Descriptions title="Responsive Descriptions" bordered :column="{ xxl: 4, xl: 3, lg: 3, md: 3, sm: 2, xs: 1 }">
    <DescriptionsItem label="Product">Cloud Database</DescriptionsItem>
    <DescriptionsItem label="Billing">Prepaid</DescriptionsItem>
    <DescriptionsItem label="Time">18:00:00</DescriptionsItem>
    <DescriptionsItem label="Amount">$80.00</DescriptionsItem>
    <DescriptionsItem label="Discount">$20.00</DescriptionsItem>
    <DescriptionsItem label="Official">$60.00</DescriptionsItem>
    <DescriptionsItem label="Config Info">
      Data disk type: MongoDB
      <br />
      Database version: 3.4
      <br />
      Package: dds.mongo.mid
      <br />
      Storage space: 10 GB
      <br />
      Replication factor: 3
      <br />
      Region: East China 1
    </DescriptionsItem>
  </Descriptions>
</template>

垂直

Show Code
vue
<template>
  <Descriptions title="User Info" layout="vertical">
    <DescriptionsItem label="UserName">Zhou Maomao</DescriptionsItem>
    <DescriptionsItem label="Telephone">1810000000</DescriptionsItem>
    <DescriptionsItem label="Live">Hangzhou, Zhejiang</DescriptionsItem>
    <DescriptionsItem label="Address" :span="2">
      No. 18, Wantang Road, Xihu District, Hangzhou, Zhejiang, China
    </DescriptionsItem>
    <DescriptionsItem label="Remark">empty</DescriptionsItem>
  </Descriptions>
</template>

垂直带边框的

Show Code
vue
<template>
  <Descriptions title="User Info" layout="vertical" bordered>
    <DescriptionsItem label="Product">Cloud Database</DescriptionsItem>
    <DescriptionsItem label="Billing Mode">Prepaid</DescriptionsItem>
    <DescriptionsItem label="Automatic Renewal">YES</DescriptionsItem>
    <DescriptionsItem label="Order time">2018-04-24 18:00:00</DescriptionsItem>
    <DescriptionsItem label="Usage Time" :span="2">2030-10-10 18:00:00</DescriptionsItem>
    <DescriptionsItem label="Status" :span="3">
      <Badge status="processing" ripple text="Running" />
    </DescriptionsItem>
    <DescriptionsItem label="Negotiated Amount">$80.00</DescriptionsItem>
    <DescriptionsItem label="Discount">$20.00</DescriptionsItem>
    <DescriptionsItem label="Official Receipts">$60.00</DescriptionsItem>
    <DescriptionsItem label="Config Info">
      Data disk type: MongoDB
      <br />
      Database version: 3.4
      <br />
      Package: dds.mongo.mid
      <br />
      Storage space: 10 GB
      <br />
      Replication factor: 3
      <br />
      Region: East China 1
      <br />
    </DescriptionsItem>
  </Descriptions>
</template>

无冒号

使用 colon 属性关闭标签后的冒号


Show Code
vue
<template>
  <Descriptions title="User Info" :colon="false">
    <DescriptionsItem label="UserName">Zhou Maomao</DescriptionsItem>
    <DescriptionsItem label="Telephone">1810000000</DescriptionsItem>
    <DescriptionsItem label="Live">Hangzhou, Zhejiang</DescriptionsItem>
  </Descriptions>
</template>

标签对齐

Show Code
vue
<script setup lang="ts">
import { ref } from 'vue'
const labelAlign = ref('left')
const labelAlignOptions = [
  {
    label: 'left',
    value: 'left'
  },
  {
    label: 'right',
    value: 'right'
  },
  {
    label: 'center',
    value: 'center'
  }
]
</script>
<template>
  <Flex vertical gap="middle">
    <Radio :options="labelAlignOptions" v-model:value="labelAlign" button button-style="solid" />
    <Descriptions title="User Info" bordered :labelAlign="labelAlign">
      <DescriptionsItem label="UserName">Zhou Maomao</DescriptionsItem>
      <DescriptionsItem label="Telephone">1810000000</DescriptionsItem>
      <DescriptionsItem label="Live">Hangzhou, Zhejiang</DescriptionsItem>
    </Descriptions>
  </Flex>
</template>

自定义类名

Show Code
vue
<template>
  <Descriptions
    bordered
    title="Custom Class"
    labelClass="descriptions-demo-label"
    contentClass="descriptions-demo-content"
  >
    <DescriptionsItem label="Product">Cloud Database</DescriptionsItem>
    <DescriptionsItem label="Billing">Prepaid</DescriptionsItem>
    <DescriptionsItem label="Time">18:00:00</DescriptionsItem>
  </Descriptions>
</template>

<style lang="less">
/**
 * 自定义类名用例的演示样式。
 * 类名落在 Descriptions 内部元素上,而 `:deep()` 编译出的选择器与组件自身样式同优先级(均为 0,2,0),
 * 胜负取决于样式注入顺序(HMR 下不稳定,实测会被组件样式覆盖)。
 * 故改用非 scoped + 更高优先级选择器,保证演示效果稳定生效。
 */
.descriptions-wrap .descriptions-item-label.descriptions-demo-label {
  color: #1677ff;
  font-weight: 600;
}

.descriptions-wrap .descriptions-item-content.descriptions-demo-content {
  color: #52c41a;
}
</style>

自定义头部

使用 header 插槽自定义整个头部区域,替代 titleextra


Show Code
vue
<template>
  <Descriptions>
    <template #header>
      <Flex gap="middle" align="center" justify="space-between" style="width: 100%">
        <span style="font-weight: 600; font-size: 16px">Custom Header</span>
        <Button type="primary">Edit</Button>
      </Flex>
    </template>
    <DescriptionsItem label="Product">Cloud Database</DescriptionsItem>
    <DescriptionsItem label="Billing">Prepaid</DescriptionsItem>
    <DescriptionsItem label="Time">18:00:00</DescriptionsItem>
  </Descriptions>
</template>

自定义内容 & 标签样式

Show Code
vue
<template>
  <Flex vertical gap="middle">
    <Descriptions
      bordered
      title="Custom Style"
      :labelStyle="{ fontWeight: 800, color: '#faad14' }"
      :contentStyle="{ fontWeight: 600, color: '#1677ff' }"
    >
      <template #extra>
        <Button type="primary">Edit</Button>
      </template>
      <DescriptionsItem label="Product">Cloud Database</DescriptionsItem>
      <DescriptionsItem label="Billing">Prepaid</DescriptionsItem>
      <DescriptionsItem label="Time">18:00:00</DescriptionsItem>
      <DescriptionsItem label="Amount" :labelStyle="{ color: '#52c41a' }" :contentStyle="{ color: '#ff4d4f' }"
        >$80.00</DescriptionsItem
      >
      <DescriptionsItem label="Discount">$20.00</DescriptionsItem>
      <DescriptionsItem label="Official">$60.00</DescriptionsItem>
      <DescriptionsItem label="Config Info">
        Data disk type: MongoDB
        <br />
        Database version: 3.4
        <br />
        Package: dds.mongo.mid
        <br />
        Storage space: 10 GB
        <br />
        Replication factor: 3
        <br />
        Region: East China 1
        <br />
      </DescriptionsItem>
    </Descriptions>
    <Descriptions
      title="Custom Style"
      :labelStyle="{ fontWeight: 800, color: '#faad14' }"
      :contentStyle="{ fontWeight: 600, color: '#1677ff' }"
    >
      <template #extra>
        <Button type="primary">Edit</Button>
      </template>
      <DescriptionsItem label="Product">Cloud Database</DescriptionsItem>
      <DescriptionsItem label="Billing">Prepaid</DescriptionsItem>
      <DescriptionsItem label="Time">18:00:00</DescriptionsItem>
      <DescriptionsItem label="Amount" :labelStyle="{ color: '#52c41a' }" :contentStyle="{ color: '#ff4d4f' }"
        >$80.00</DescriptionsItem
      >
      <DescriptionsItem label="Discount">$20.00</DescriptionsItem>
      <DescriptionsItem label="Official">$60.00</DescriptionsItem>
    </Descriptions>
  </Flex>
</template>

描述列表配置器

title:
extra:
bordered:
layout:
size:
default
colon:
column:
统一列数
响应式断点
所有视口统一为 3 列
labelAlign:
left
labelStyle fontSize:
labelStyle color:
#FF6900
labelStyle fontWeight:
contentStyle fontSize:
contentStyle color:
#1677FF
contentStyle fontWeight:
User Info
extra
ProductCloud Database
BillingPrepaid
Time18:00:00
Amount$80.00
Discount$20.00
Official$60.00
Status
Running
Usage Time2030-04-24 18:00:00
AddressNo. 18, Wantang Road, Xihu District, Hangzhou, Zhejiang, China
Show Code
vue
<script setup lang="ts">
import { ref, reactive, computed, onMounted } from 'vue'
import { useWindowSize } from '@vueuse/core'
const options = [
  {
    label: 'default',
    value: 'default'
  },
  {
    label: 'middle',
    value: 'middle'
  },
  {
    label: 'small',
    value: 'small'
  }
]
const labelAlignOptions = [
  {
    label: 'left',
    value: 'left'
  },
  {
    label: 'right',
    value: 'right'
  },
  {
    label: 'center',
    value: 'center'
  }
]
// column 断点:与组件 Responsive 断点一一对应,rule 直观标注生效区间,min / max 用于判断当前视口命中项
const breakpoints = [
  { key: 'xs', rule: '<576px', min: 0, max: 575 },
  { key: 'sm', rule: '≥576px', min: 576, max: 767 },
  { key: 'md', rule: '≥768px', min: 768, max: 991 },
  { key: 'lg', rule: '≥992px', min: 992, max: 1199 },
  { key: 'xl', rule: '≥1200px', min: 1200, max: 1599 },
  { key: 'xxl', rule: '≥1600px', min: 1600, max: 1999 },
  { key: 'xxxl', rule: '≥2000px', min: 2000, max: Infinity }
]
const columnModeOptions = [
  { label: '统一列数', value: 'number' },
  { label: '响应式断点', value: 'responsive' }
]
const { width } = useWindowSize()
// 未挂载前不渲染依赖视口的反馈,避免服务端与客户端首屏输出不一致
const isMounted = ref(false)
onMounted(() => {
  isMounted.value = true
})
// 当前视口命中的断点:判定口径与组件一致(从大到小取第一个命中项)
const currentBreakpoint = computed(() => {
  if (!isMounted.value) {
    return undefined
  }
  return breakpoints.find((bp) => width.value >= bp.min && width.value <= bp.max)?.key
})
const state = reactive({
  title: 'User Info',
  extra: 'extra',
  bordered: false,
  layout: 'horizontal',
  size: 'default',
  colon: true,
  columnMode: 'number',
  columnValue: 3,
  column: {
    xs: 1,
    sm: 2,
    md: 3,
    lg: 3,
    xl: 3,
    xxl: 3,
    xxxl: 3
  },
  labelAlign: 'left',
  labelStyle: {
    fontSize: '14px',
    color: '#FF6900',
    fontWeight: 600
  },
  contentStyle: {
    fontSize: '14px',
    color: '#1677FF',
    fontWeight: 400
  }
})
// 配置器最终传给组件的 column:统一列数传数值,响应式断点传对象
const columnConfig = computed(() => (state.columnMode === 'number' ? state.columnValue : state.column))
// 实时反馈当前实际生效的列数,帮助理解断点规则
const activeColumnTip = computed(() => {
  if (state.columnMode === 'number') {
    return `所有视口统一为 ${state.columnValue} 列`
  }
  const key = currentBreakpoint.value
  if (!key) {
    return '正在检测当前视口…'
  }
  const rule = breakpoints.find((bp) => bp.key === key)?.rule
  return `当前视口 ${width.value}px,命中 ${key}(${rule}),实际 ${state.column[key]} 列`
})
</script>
<template>
  <Flex vertical>
    <Row :gutter="[24, 12]">
      <Col :span="6">
        <Flex gap="small" vertical>
          title:
          <Input v-model:value="state.title" placeholder="title" />
        </Flex>
      </Col>
      <Col :span="6">
        <Flex gap="small" vertical>
          extra:
          <Input v-model:value="state.extra" placeholder="extra" />
        </Flex>
      </Col>
      <Col :span="6">
        <Space gap="small" vertical>
          bordered:
          <Switch v-model="state.bordered" />
        </Space>
      </Col>
      <Col :span="6">
        <Space gap="small" vertical>
          layout:
          <Switch v-model="state.layout" checked-value="vertical" un-checked-value="horizontal" />
        </Space>
      </Col>
      <Col :span="6">
        <Flex gap="small" vertical>
          size:
          <Select :options="options" v-model="state.size" />
        </Flex>
      </Col>
      <Col :span="6">
        <Space gap="small" vertical>
          colon:
          <Switch v-model="state.colon" />
        </Space>
      </Col>
      <Col :span="24">
        <Flex gap="small" vertical>
          <Flex gap="middle" align="center" wrap="wrap">
            column:
            <Segmented v-model:value="state.columnMode" :options="columnModeOptions" />
            <InputNumber
              v-if="state.columnMode === 'number'"
              v-model:value="state.columnValue"
              :min="1"
              :max="9"
            />
            <span class="descriptions-column-tip">{{ activeColumnTip }}</span>
          </Flex>
          <Flex v-if="state.columnMode === 'responsive'" gap="middle" align="flex-start" wrap="wrap">
            <Flex
              v-for="bp in breakpoints"
              :key="bp.key"
              gap="small"
              vertical
              align="center"
              class="descriptions-column-breakpoint"
            >
              <Tag size="small" :color="bp.key === currentBreakpoint ? 'processing' : undefined">
                {{ bp.key }}
              </Tag>
              <span class="descriptions-column-rule">{{ bp.rule }}</span>
              <InputNumber v-model:value="state.column[bp.key]" :min="1" :max="9" />
            </Flex>
          </Flex>
        </Flex>
      </Col>
      <Col :span="6">
        <Flex gap="small" vertical>
          labelAlign:
          <Select :options="labelAlignOptions" v-model="state.labelAlign" />
        </Flex>
      </Col>
      <Col :span="6">
        <Flex gap="small" vertical>
          labelStyle fontSize:
          <Input v-model:value="state.labelStyle.fontSize" placeholder="labelStyle fontSize" />
        </Flex>
      </Col>
      <Col :span="6">
        <Flex gap="small" vertical>
          labelStyle color:
          <ColorPicker v-model:value="state.labelStyle.color" />
        </Flex>
      </Col>
      <Col :span="6">
        <Flex gap="small" vertical>
          labelStyle fontWeight:
          <InputNumber
            v-model:value="state.labelStyle.fontWeight"
            :step="100"
            :min="100"
            :max="1000"
            placeholder="labelStyle fontWeight"
          />
        </Flex>
      </Col>
      <Col :span="6">
        <Flex gap="small" vertical>
          contentStyle fontSize:
          <Input v-model:value="state.contentStyle.fontSize" placeholder="contentStyle fontSize" />
        </Flex>
      </Col>
      <Col :span="6">
        <Flex gap="small" vertical>
          contentStyle color:
          <ColorPicker v-model:value="state.contentStyle.color" />
        </Flex>
      </Col>
      <Col :span="6">
        <Flex gap="small" vertical>
          contentStyle fontWeight:
          <InputNumber
            v-model:value="state.contentStyle.fontWeight"
            :step="100"
            :min="100"
            :max="1000"
            placeholder="contentStyle fontWeight"
          />
        </Flex>
      </Col>
    </Row>
    <Descriptions
      :title="state.title"
      :extra="state.extra"
      :bordered="state.bordered"
      :layout="state.layout"
      :size="state.size"
      :colon="state.colon"
      :column="columnConfig"
      :label-align="state.labelAlign"
      :label-style="state.labelStyle"
      :content-style="state.contentStyle"
    >
      <DescriptionsItem label="Product">Cloud Database</DescriptionsItem>
      <DescriptionsItem label="Billing">Prepaid</DescriptionsItem>
      <DescriptionsItem label="Time">18:00:00</DescriptionsItem>
      <DescriptionsItem label="Amount">$80.00</DescriptionsItem>
      <DescriptionsItem label="Discount">$20.00</DescriptionsItem>
      <DescriptionsItem label="Official">$60.00</DescriptionsItem>
      <DescriptionsItem label="Status" :span="1">
        <Badge status="processing" ripple text="Running" />
      </DescriptionsItem>
      <DescriptionsItem label="Usage Time" :span="2">2030-04-24 18:00:00</DescriptionsItem>
      <DescriptionsItem label="Address" :span="3"
        >No. 18, Wantang Road, Xihu District, Hangzhou, Zhejiang, China</DescriptionsItem
      >
    </Descriptions>
  </Flex>
</template>
<style lang="less">
.descriptions-column-breakpoint {
  width: 90px;
}

.descriptions-column-rule,
.descriptions-column-tip {
  font-size: 12px;
  color: rgba(0, 0, 0, 0.45);
}
</style>

APIs

Descriptions

参数说明类型默认值
title描述列表的标题,显示在最顶部string | VNodeundefined
extra描述列表的操作区域,显示在右上方string | VNodeundefined
bordered是否展示边框booleanfalse
layout描述列表布局方式'horizontal' | 'vertical''horizontal'
size设置列表的大小'default' | 'middle' | 'small''default'
colon是否显示标签后的冒号(边框模式不显示冒号)booleantrue
column一行的 DescriptionsItem 数量,可以写成数值或支持响应式的对象写法 { xs: 8, sm: 16, md: 24 }number | DescriptionsResponsive{xs: 1, sm: 2, md: 3, lg: 3, xl: 3, xxl: 3, xxxl: 3}
labelAlign标签对齐方式'left' | 'right' | 'center''left'
labelStyle自定义标签样式,优先级低于 DescriptionsItemlabelStyleCSSPropertiesundefined
contentStyle自定义内容样式,优先级低于 DescriptionsItemcontentStyleCSSPropertiesundefined
labelClass标签自定义类名,与 DescriptionsItemlabelClass 叠加stringundefined
contentClass内容自定义类名,与 DescriptionsItemcontentClass 叠加stringundefined

Responsive Type

名称说明类型默认值
xs<576px 响应式栅格numberundefined
sm≥576px 响应式栅格numberundefined
md≥768px 响应式栅格numberundefined
lg≥992px 响应式栅格numberundefined
xl≥1200px 响应式栅格numberundefined
xxl≥1600px 响应式栅格numberundefined
xxxl≥2000px 响应式栅格numberundefined

DescriptionsItem

参数说明类型默认值
label内容的描述标签string | number | VNodeundefined
span包含列的数量,未设置时按 1 处理;最后一行的最后一项未设置 span(或显式 span 超出本行剩余列数)时收缩为剩余列数,即补满该行,显式 span 未超出本行剩余列数时按显式值渲染number1
labelStyle自定义标签样式,优先级高于 DescriptionslabelStyleCSSPropertiesundefined
contentStyle自定义内容样式,优先级高于 DescriptionscontentStyleCSSPropertiesundefined
labelClass标签自定义类名,与 DescriptionslabelClass 叠加stringundefined
contentClass内容自定义类名,与 DescriptionscontentClass 叠加stringundefined

同一行 span 之和超过 column 时,超出本行剩余列数的项会收缩为剩余列数(开发环境会给出提示)。

Slots

Descriptions Slots

名称说明类型
default自定义描述列表内容v-slot:default
header自定义整个头部区域,存在时替代 titleextrav-slot:header
title自定义描述列表的标题v-slot:title
extra自定义描述列表的操作区域v-slot:extra

DescriptionsItem Slots

名称说明类型
label自定义描述标签v-slot:label
default自定义内容v-slot:default

Released under the MIT License.