常规的卡片容器,可以承载标题、段落、图片、列表等内容。
支持两种使用方式:配置式(通过 props 驱动)和复合式(通过子组件组装)。
- 需要承载多个内容元素时。
- 需要分组展示信息时。
- 需要配合栅格布局展示信息卡片时。
import {
Card,
CardHeader,
CardTitle,
CardDescription,
CardContent,
CardFooter,
CardMeta,
CardGroup,
} from "@reglow/reui";
通过 title、cover、footer 等 props 配置卡片结构,适合数据驱动的场景:
<script setup>
import { Card } from "@reglow/reui";
</script>
<template>
<Card title="标题" header-extra-content="更多" style="max-width: 360px">
<p>卡片内容</p>
</Card>
</template>
通过 CardHeader、CardContent 等子组件手动组装,适合自定义结构的场景:
<script setup>
import {
Card,
CardHeader,
CardTitle,
CardDescription,
CardContent,
CardFooter,
} from "@reglow/reui";
</script>
<template>
<Card style="max-width: 360px">
<CardHeader>
<CardTitle>标题</CardTitle>
<CardDescription>描述文字</CardDescription>
</CardHeader>
<CardContent>
<p>卡片内容</p>
</CardContent>
<CardFooter>
<p>页脚</p>
</CardFooter>
</Card>
</template>
Card 会自动检测模式:当传入 title、cover、footer、loading 等配置 props 或具名插槽时使用配置式,否则使用复合式(纯容器 + 默认插槽)。复合式默认带阴影。
包含标题、内容和标题右侧额外内容。
<script setup>
import { Card } from "@reglow/reui";
</script>
<template>
<Card
title="Semi Design"
style="max-width: 360px"
header-extra-content="更多"
>
<p>Semi Design 是由抖音前端团队与 UED 团队共同设计开发并维护的设计系统。</p>
</Card>
</template>
只设置内容区域。
<script setup>
import { Card } from "@reglow/reui";
</script>
<template>
<Card style="max-width: 360px">
<p>Semi Design 是由抖音前端团队与 UED 团队共同设计开发并维护的设计系统。</p>
</Card>
</template>
通过 cover 设置封面。
<script setup>
import { Card, CardMeta } from "@reglow/reui";
import { h } from "vue";
</script>
<template>
<Card
style="max-width: 300px"
:cover="h('img', { src: 'https://picsum.photos/300/200', alt: 'cover' })"
>
<CardMeta title="卡片封面" />
</Card>
</template>
通过 bordered 设置外边框,headerLine / footerLine 设置边线。
<script setup>
import { Card } from "@reglow/reui";
</script>
<template>
<Card
style="max-width: 360px"
:bordered="false"
:header-line="true"
title="Semi Design"
>
<p>无边框卡片,标题区有边线。</p>
</Card>
</template>
通过 shadows 设置显示阴影的时机。
<script setup>
import { Card } from "@reglow/reui";
</script>
<template>
<!-- hover 时显示阴影 -->
<Card shadows="hover" style="max-width: 360px">
<p>鼠标悬停时显示阴影。</p>
</Card>
<!-- 始终显示阴影 -->
<Card shadows="always" style="max-width: 360px">
<p>始终显示阴影。</p>
</Card>
</template>
利用 CardMeta 设置 title、description、avatar。
<script setup>
import { Card, CardMeta } from "@reglow/reui";
import { h } from "vue";
</script>
<template>
<Card style="max-width: 340px">
<CardMeta
title="Semi Doc"
description="全面、易用、优质"
:avatar="
h('img', {
src: 'https://picsum.photos/40/40',
class: 'w-10 h-10 rounded-full',
})
"
/>
</Card>
</template>
卡片嵌套。
<script setup>
import { Card } from "@reglow/reui";
</script>
<template>
<Card title="Card title">
<Card title="Inner Card title" class="mb-4" header-extra-content="更多">
<p>Inner Card content</p>
</Card>
<Card title="Inner Card title" header-extra-content="更多">
<p>Inner Card content</p>
</Card>
</Card>
</template>
通过 loading 显示占位元素。
<script setup>
import { ref } from "vue";
import { Card, CardMeta } from "@reglow/reui";
const loading = ref(true);
</script>
<template>
<Card :loading="loading" style="max-width: 360px">
<CardMeta title="Semi Doc" description="全面、易用、优质" />
</Card>
</template>
结合 Tabs 组件。
<script setup>
import { ref } from "vue";
import { Card } from "@reglow/reui";
import { Tabs } from "@reglow/reui";
const activeKey = ref("1");
const tabList = [
{ itemKey: "1", tab: "Tab 1" },
{ itemKey: "2", tab: "Tab 2" },
];
</script>
<template>
<Card title="Card title">
<Tabs v-model:active-key="activeKey" :tab-list="tabList">
<div v-if="activeKey === '1'">content1</div>
<div v-if="activeKey === '2'">content2</div>
</Tabs>
</Card>
</template>
通过 actions 设置操作区。
<script setup>
import { h } from "vue";
import { Card, CardMeta } from "@reglow/reui";
import { Button } from "@reglow/reui";
const actions = [
h(Button, { variant: "ghost", size: "sm" }, () => "收藏"),
h(Button, { variant: "ghost", size: "sm" }, () => "分享"),
];
</script>
<template>
<Card style="max-width: 300px" :actions="actions" :header-line="false">
<CardMeta title="Semi Doc" description="全面、易用、优质" />
</Card>
</template>
CardGroup 中的卡片等间距排列。
<script setup>
import { ref } from "vue";
import { Card, CardGroup } from "@reglow/reui";
const spacing = ref(12);
</script>
<template>
<CardGroup :spacing="spacing">
<Card
v-for="i in 8"
:key="i"
shadows="hover"
title="Card title"
:header-line="false"
style="width: 260px"
>
<p>Card content</p>
</Card>
</CardGroup>
</template>
设置 type="grid" 将卡片组设置为网格型。
<template>
<CardGroup type="grid" :spacing="16">
<Card
v-for="i in 7"
:key="i"
shadows="hover"
title="Card title"
:header-line="false"
>
<p>Card content</p>
</Card>
</CardGroup>
</template>
<template>
<Card>
<template #header>
<div class="flex items-center gap-2">
<span>自定义头部</span>
</div>
</template>
<template #cover>
<img src="https://picsum.photos/360/200" alt="cover" class="w-full" />
</template>
<p>内容区域</p>
<template #footer>
<div>页脚内容</div>
</template>
</Card>
</template>
| 参数 | 说明 | 类型 | 默认值 |
|---|
| title | 标题(配置式) | VNode | string | - |
| headerExtraContent | 标题右侧额外内容 | VNode | string | - |
| header | 自定义头部(覆盖 title 和 headerExtraContent) | VNode | string | - |
| cover | 封面 | VNode | string | - |
| footer | 页脚 | VNode | string | - |
| actions | 操作区(位于内容区底部) | (VNode | string)[] | - |
| bordered | 是否有外边框 | boolean | true |
| headerLine | 标题区与内容区是否有边线 | boolean | true |
| footerLine | 页脚区与内容区是否有边线 | boolean | false |
| loading | 加载占位 | boolean | false |
| shadows | 阴影时机 | hover | always | - |
| headerStyle | 标题区样式 | CSSProperties | - |
| bodyStyle | 内容区样式 | CSSProperties | - |
| footerStyle | 页脚区样式 | CSSProperties | - |
| class | 附加类名 | string | - |
| style | 附加样式 | CSSProperties | - |
当未传入 title、cover、footer、header、actions、headerExtraContent、loading 且未使用对应具名插槽时,Card 自动切换为复合式模式,仅渲染容器 + 默认插槽,默认带阴影。
| 名称 | 说明 |
|---|
| default | 内容(配置式为内容区,复合式为整个插槽) |
| header | 自定义头部(覆盖 title/headerExtraContent) |
| title | 标题 |
| headerExtraContent | 标题右侧额外内容 |
| cover | 封面 |
| footer | 页脚 |
| actions | 操作区 |
| 参数 | 说明 | 类型 | 默认值 |
|---|
| class | 附加类名 | string | - |
| 参数 | 说明 | 类型 | 默认值 |
|---|
| class | 附加类名 | string | - |
| 参数 | 说明 | 类型 | 默认值 |
|---|
| class | 附加类名 | string | - |
| 参数 | 说明 | 类型 | 默认值 |
|---|
| class | 附加类名 | string | - |
| 参数 | 说明 | 类型 | 默认值 |
|---|
| class | 附加类名 | string | - |
| 参数 | 说明 | 类型 | 默认值 |
|---|
| spacing | 间距尺寸(数值或 水平, 垂直) | number | number[] | 12 |
| type | 类型,设为 grid 开启网格布局 | string | - |
| class | 附加类名 | string | - |
| style | 附加样式 | CSSProperties | - |
| 参数 | 说明 | 类型 | 默认值 |
|---|
| title | 标题 | VNode | string | - |
| description | 描述 | VNode | string | - |
| avatar | 头像 | VNode | string | - |
| titleClass | 标题附加类名 | string | - |
| descriptionClass | 描述附加类名 | string | - |
| class | 附加类名 | string | - |
| style | 附加样式 | CSSProperties | - |
| 名称 | 说明 |
|---|
| default | 额外内容 |
| title | 标题 |
| description | 描述 |
| avatar | 头像 |
- Card 支持
aria-label 表示作用 - loading 时开启
aria-busy - Card 为容器型组件,内部元素需遵循各自的可访问性指南