Element Plus Card 组件完全指南:容器布局、阴影控制与源码级解析
【免费下载链接】element-plus🎉 A Vue.js 3 UI Library made by Element team项目地址: https://gitcode.com/GitHub_Trending/el/element-plus
Element Plus 的 Card(卡片)组件用于将标题、正文、操作区域等信息整合进一个统一的卡片容器中,是构建仪表盘、内容列表与详情展示的常用基础组件。本文将基于 官方文档 全面讲解 Card 的三种典型用法、全部属性与插槽 API,并结合仓库内 组件实现源码、Props 类型定义 与 单元测试 深入剖析其底层渲染机制,读完即可在真实项目中灵活组合 header、body、footer 与阴影策略。
组件定位与基本结构
Card 的核心定位是"信息整合容器":它把标题、内容和操作区域封装在同一个视觉单元中。从 card.vue 的模板结构 可以看到,组件对外呈现为三段式结构:
header:可选头部区域,存在header属性或#header插槽时才渲染;body:默认主体区域,始终渲染,承载默认插槽内容;footer:可选底部区域,存在footer属性或#footer插槽时才渲染。
其中 header 与 footer 均为可选段,内容分发依赖具名插槽。整个根节点会根据shadow属性动态追加is-always-shadow、is-hover-shadow或is-never-shadow修饰类,对应 card.scss 中的状态样式。
基础用法:header、body 与 footer 三段式布局
基础场景下,Card 由标题、正文和底部操作区三部分组成。官方示例 docs/examples/card/basic.vue 展示了完整用法:
<template> <el-card style="max-width: 480px"> <template #header> <div class="card-header"> <span>Card name</span> </div> </template> <p v-for="o in 4" :key="o" class="text item">{{ 'List item ' + o }}</p> <template #footer>Footer content</template> </el-card> </template>要点说明:
- 头部通过
#header具名插槽传入,可以是任意 DOM;也可以退而使用header字符串属性,两者等价(源码中v-if="$slots.header || header"同时监听插槽与属性,见 card.vue)。 - 正文直接写在默认插槽中,本例循环渲染 4 条列表项。
- 底部通过
#footer具名插槽渲染"Footer content",适合放置操作按钮等元素。
单元测试 card.test.tsx 验证了两种头部传值方式:字符串属性header="I am header"与 VNode 插槽(包含 span 与 button 的复杂 DOM)都能正确渲染,说明插槽方式支持更灵活的富内容。
简单卡片:省略头部
当页面只需要纯内容展示时,可以省略头部区域。官方示例 docs/examples/card/simple.vue 是最精简形态:
<template> <el-card style="max-width: 480px"> <p v-for="o in 4" :key="o" class="text item">{{ 'List item ' + o }}</p> </el-card> </template>此时既不传header属性也没有#header插槽,模板中的头部div不会渲染,卡片退化为纯 body 容器。footer 同理:只有提供对应属性或插槽时才渲染。
带图片的卡片:body-style 自定义正文样式
通过body-style属性可以为正文区域注入自定义 CSS 样式,从而让卡片承载图片、富媒体等更丰富的内容。官方示例 docs/examples/card/with-images.vue:
<template> <el-card style="max-width: 480px"> <template #header>Yummy hamburger</template> <img src="https://shadow.elemecdn.com/app/element/hamburger.9cf7b091-55e9-11e9-a976-7f4d0b07eef6.png" style="width: 100%" /> </el-card> </template>body-style的类型为 Vue 的StyleValue。从 card.ts 的属性定义 可以看到,它通过definePropType<StyleValue>([String, Object, Array, Boolean])声明,即同时支持:
- 字符串形式:如
"font-size: 14px;"; - 对象形式:如
{ 'font-size': '14px' }; - 数组形式:如
[{ 'font-size': '14px' }, { color: 'blue' }],多个样式对象合并生效。
单元测试 对这三种形式逐一断言,验证最终都会正确落在.el-card__body元素的内联style属性上。此外,body-style的值会直接绑定到 body 的:style上(见 card.vue),因此也支持以;分隔的多条声明。
阴影控制:always、hover 与 never
shadow属性决定卡片阴影的显示时机,可选值为always(始终显示)、hover(悬停时显示)与never(从不显示),默认always。官方示例 docs/examples/card/shadow.vue:
<template> <div class="flex flex-wrap gap-4"> <el-card style="width: 480px" shadow="always">Always</el-card> <el-card style="width: 480px" shadow="hover">Hover</el-card> <el-card style="width: 480px" shadow="never">Never</el-card> </div> </template>底层实现上,根节点类名由ns.is(${shadow || globalConfig?.shadow || 'always'}-shadow)计算(见 card.vue),再配合 card.scss 中.is-always-shadow与.is-hover-shadow的 box-shadow 规则(hover模式还监听了:focus状态)。值得注意的细节:
shadow属性默认值为undefined,最终回落到'always';- 支持从
ConfigProvider的全局配置中读取默认阴影策略(useGlobalConfig('card')),即项目级统一定义卡片阴影风格; - 单元测试 确认了类名拼接逻辑,例如
shadow="always"会生成.is-always-shadow类。
完整 API 参考
以下 API 信息与官方文档 card.md 保持一致,并结合 card.ts 补充了更精确的类型细节。
Attributes 属性
| 名称 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| header | 卡片标题,也接受通过slot#header传入的 DOM | ^[string] | — |
| footer ^(2.4.3) | 卡片底部内容,也接受通过slot#footer传入的 DOM | ^[string] | — |
| body-style | 卡片正文的 CSS 样式 | ^[object]CSSProperties | — |
| header-class ^(2.9.8) | 卡片头部自定义类名 | ^[string] | — |
| body-class ^(2.3.10) | 卡片正文自定义类名 | ^[string] | — |
| footer-class ^(2.9.8) | 卡片底部自定义类名 | ^[string] | — |
| shadow | 卡片阴影显示时机 | ^[enum]always \| never \| hover | always |
补充说明:
header与footer属性在 card.ts 中默认值为空字符串'',仅作纯文本兜底,富内容请优先使用具名插槽。- 三个
*-class属性的类型为ClassValue,实际声明为[String, Array, Object, Boolean],因此支持字符串、数组(多类名)、对象(条件类名)三种写法。 - 上述 class 属性在 card.vue 中分别拼接在
.el-card__header、.el-card__body、.el-card__footer上,单元测试 已验证三个类名均正确挂载。
Slots 插槽
| 名称 | 说明 |
|---|---|
| default | 自定义默认内容 |
| header | 卡片头部内容 |
| footer | 卡片底部内容 |
样式定制要点
卡片样式基于 CSS 变量驱动,位于 packages/theme-chalk/src/card.scss。可通过覆盖变量实现主题定制:
card-padding:header/body/footer 的内边距基准值,header 与 footer 实际为padding - 2px;card-border-radius:卡片圆角;card-border-color:边框与分隔线颜色;card-bg-color:卡片背景色。
布局上,卡片根节点为flex-direction: column的纵向弹性布局,body 设置了flex-grow: 1与overflow: auto,因此在弹性父容器中能自动撑满剩余高度并独立滚动,适合构建可滚动内容区。结合上述 CSS 变量即可无侵入地完成卡片圆角、间距与阴影深浅的品牌化定制。
实战小结
通过本文可以掌握 Element Plus Card 组件从"最小可用"到"富内容卡片"的完整路径:
- 基础三段式布局:
#header+ 默认插槽 +#footer; - 精简形态:省略 header/footer 得到纯内容容器;
- 富媒体扩展:用
body-style(字符串/对象/数组三种写法)定制正文样式; - 交互反馈:用
shadow三态(always/hover/never)控制阴影时机,并结合 ConfigProvider 实现全局默认阴影策略; - 精细定制:通过
header-class、body-class、footer-class挂载自定义类,配合 SCSS 变量统一主题。
相关源码与示例可进一步查阅:组件模板与逻辑、Props 定义、单元测试、样式源码 以及 完整示例目录。
【免费下载链接】element-plus🎉 A Vue.js 3 UI Library made by Element team项目地址: https://gitcode.com/GitHub_Trending/el/element-plus
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考