- 前端
- UI组件
- 设计系统
【免费下载链接】ant-design-vue
🌈 An enterprise-class UI components based on Ant Design and Vue. 🐜
Skeleton 是 Ant Design Vue(ant-design-vue)提供的内容加载占位组件:当页面数据尚未就绪时,用灰色骨架块预先勾勒出标题、段落、头像、按钮、输入框等元素的轮廓,避免布局跳动、降低用户等待焦虑。本文以 components/skeleton/index.en-US.md 文档为主体,结合组件源码(Skeleton.tsx、Element.tsx、Paragraph.tsx等)与官方示例(components/skeleton/demo/),完整讲解全部 API、组合用法、loading切换机制以及底层实现原理,读完即可在项目中落地一套高质量的骨架屏方案。
什么时候使用 Skeleton
官方文档给出了四条核心使用建议:
- 资源需要长时间加载时:例如图表数据、详情接口返回前的等待阶段;
- 组件包含大量信息时:典型的如 List 列表、Card 卡片,一次性渲染大量结构,骨架屏能有效缓解首屏白屏;
- 仅在首次加载数据时生效:Skeleton 定位是"首次加载"占位,二次刷新建议复用已缓存的结构或直接展示内容;
- 可被 Spin 替代,但体验更优:任何场景下都可用 Spin 加载态替代,但 Skeleton 通过勾勒真实内容轮廓(标题、段落、头像),让用户预知页面结构,感知上更流畅、更接近最终形态。
简单地说:Spin 表达"系统正在加载",Skeleton 表达"内容长这样、马上就好"。
快速上手:基础用法与组合骨架
最简单的骨架屏只需要一行模板:
<template> <a-skeleton /> </template>对应官方示例 components/skeleton/demo/basic.vue。默认渲染一个包含"标题 + 段落"的占位块。在 Skeleton.tsx 中可以看到默认值定义:
props: initDefaultProps(skeletonProps(), { avatar: false, title: true, paragraph: true, }),即默认显示title(标题占位)和paragraph(段落占位),不显示avatar。
更贴近真实场景的是复杂布局示例 components/skeleton/demo/complex.vue(组合头像 + 标题 + 段落)以及列表示例 components/skeleton/demo/list.vue。头像 + 标题 + 段落的组合会自动生成一套经过视觉优化的默认比例,这一逻辑由 Skeleton.tsx 中的三个辅助函数完成:
getAvatarBasicProps:当"有标题且无段落"时返回{ size: 'large', shape: 'square' }(方形大头像),否则返回{ size: 'large', shape: 'circle' }(圆形头像);getTitleBasicProps:无头像有段落时标题宽度38%,有头像有段落时标题宽度50%;getParagraphBasicProps:默认行数 2 行,无头像或无标题时末行宽度61%,仅标题无头像时行数调整为 3 行。
也就是说,你只管声明"要哪些块",组件会自动编排出一套协调的骨架比例,无需手动逐个调宽度。
API 详解:Skeleton 核心属性
文档中 Skeleton 组件的完整属性表如下:
| Property | Description | Type | Default |
|---|---|---|---|
| active | 显示动画效果(闪烁/呼吸渐变) | boolean | false |
| avatar | 显示头像占位 | boolean | SkeletonAvatarProps | false |
| loading | 为true时显示骨架 | boolean | - |
| paragraph | 显示段落占位 | boolean | SkeletonParagraphProps | true |
| title | 显示标题占位 | boolean | SkeletonTitleProps | true |
对应源码 skeletonProps(),注意源码中还有文档未列出的prefixCls与round两个内部/扩展属性:
active:开启后骨架块呈现从左到右的流光扫过动画,用于提示"正在加载中";avatar/title/paragraph:既可传布尔值,也可传对象。传true/false控制是否渲染该块;传对象则进一步定制该块的形状、尺寸、宽度等细节(见下文三个子 Props 表);loading:核心的"真实内容切换"开关。当loading为true时渲染骨架,为false时渲染插槽(default slot)中的真实内容。源码判断逻辑见 Skeleton.tsx:
if (loading || props.loading === undefined) { // ...渲染骨架占位 } return slots.default?.();关键细节:当
loading**未传值(undefined)**时,Skeleton 默认也渲染骨架——这与文档中 Default 列为-的行为一致,意味着该组件天然作为"默认占位"存在。只有显式传入loading={false}才会展示真实内容。
加载完成切换:loading 与子组件插槽
官方示例 components/skeleton/demo/children.vue 展示了最经典的使用模式:先用a-skeleton包裹真实内容,再通过loading布尔值控制切换:
<template> <a-space direction="vertical" style="width: 100%" :size="16"> <a-skeleton :loading="loading"> <div> <h4>Ant Design Vue, a design language</h4> <p>We supply a series of design principles, practical patterns and high quality design resources (Sketch and Axure), to help people create their product prototypes beautifully and efficiently.</p> </div> </a-skeleton> <a-button :disabled="loading" @click="showSkeleton">Show Skeleton</a-button> </a-space> </template> <script lang="ts" setup> import { ref } from 'vue'; const loading = ref<boolean>(false); const showSkeleton = () => { loading.value = true; setTimeout(() => { loading.value = false; }, 3000); }; </script>这一段就是骨架屏在真实业务中的标准用法:数据请求发出时loading = true显示骨架,接口返回后loading = false切换为真实内容。由于骨架与真实内容处于同一布局位置,切换时页面结构几乎不变,不会产生"先空白、后跳动"的割裂感。对应源码正是上文slots.default?.()的插槽渲染逻辑。
子属性配置:头像、标题、段落
SkeletonAvatarProps(头像)
| Property | Description | Type | Default |
|---|---|---|---|
| shape | 头像形状 | circle|square | - |
| size | 头像尺寸 | number |large|small|default | - |
用法示例:
<a-skeleton :avatar="{ size: 'large', shape: 'square' }" />源码见 Avatar.tsx:shape支持circle/square,size除枚举值外还支持数字(此时按像素渲染宽高)。数值尺寸的最终落地在 Element.tsx:
const sizeStyle: CSSProperties = typeof size === 'number' ? { width: `${size}px`, height: `${size}px`, lineHeight: `${size}px` } : {};SkeletonTitleProps(标题)
| Property | Description | Type | Default |
|---|---|---|---|
| width | 标题宽度 | number | string | - |
Title.tsx 的实现非常精简:数字会被自动追加px单位,字符串(如'50%')直接作为 CSS width 使用:
const zWidth = typeof width === 'number' ? `${width}px` : width; return <h3 class={prefixCls} style={{ width: zWidth }} />;SkeletonParagraphProps(段落)
| Property | Description | Type | Default |
|---|---|---|---|
| rows | 段落行数 | number | - |
| width | 段落宽度。传入数组时可为每一行单独设置宽度;否则只设置最后一行的宽度 | number | string | Array<number | string> | - |
这是 Skeleton 中最灵活的配置。源码 Paragraph.tsx 展示了它的"数组逐行 + 非数组仅末行"语义:
const getWidth = (index: number) => { const { width, rows = 2 } = props; if (Array.isArray(width)) { return width[index]; // 数组:逐行取对应宽度 } // 非数组:仅最后一行(rows - 1 === index)使用该宽度 if (rows - 1 === index) { return width; } return undefined; };示例:
<a-skeleton :paragraph="{ rows: 4, width: ['40%', '80%', '60%', '90%'] }" /> <!-- 四行段落,每行宽度各不相同;省略数组时 width 只作用于最后一行 -->组合子组件:Skeleton.Button / Input / Image / Avatar / Title(3.0+)
文档指出SkeletonButtonProps与SkeletonInputProps为 3.0+ 新增能力。除了主Skeleton组件外,ant-design-vue 还以静态属性的形式挂载了 5 个独立子组件(见 components/skeleton/index.tsx):Skeleton.Button、Skeleton.Avatar、Skeleton.Input、Skeleton.Image、Skeleton.Title,全部通过Skeleton.install一并注册到应用中,模板中可直接使用a-skeleton-button、a-skeleton-avatar、a-skeleton-input、a-skeleton-image等标签。每个子组件的尺寸基准(large/small/default)与对应真实组件保持一致,保证"骨架形态 ≈ 真实形态"。
SkeletonButtonProps(骨架按钮)
| Property | Description | Type | Default |
|---|---|---|---|
| active | 显示动画效果 | boolean | false |
| block | 是否撑满父容器宽度 | boolean | false |
| shape | 按钮形状 | circle|round|default | - |
| size | 按钮尺寸 | large|small|default | - |
SkeletonInputProps(骨架输入框)
| Property | Description | Type | Default |
|---|---|---|---|
| active | 显示动画效果 | boolean | false |
| size | 输入框尺寸 | large|small|default | - |
SkeletonImage(骨架图片)
源码 Image.tsx 内置了一段 SVG 图片占位(viewBox="0 0 1098 1024"的山水图形路径),无需任何 props 即可渲染一个带图标轮廓的图片占位块,适用于商品图、封面图等场景。
官方示例 components/skeleton/demo/element.vue 综合演示了按钮、头像、输入框、图片的搭配,并附带了active(动画开关)、block(按钮撑满)、size(尺寸切换)、shape(形状切换)的交互控制面板,是理解这几个子组件最直观的参考。组件内部结构上,Button/Input/Avatar/Image均复用 Element.tsx 作为最终渲染单元——Element根据size追加-lg/-sm类、根据shape追加-circle/-square/-round类,数字尺寸直接以内联样式设置宽高。
源码级补充:RTL、主题样式与注册机制
- RTL 支持:主组件在 Skeleton.tsx 中通过
direction.value === 'rtl'追加-rtl类,配合useConfigInject自动感知 ConfigProvider 的方向配置,无需手动处理镜像布局; - 样式注入:组件通过
useStyle(cssinjs 方案,见 components/skeleton/style/index.ts)在渲染时按需注入样式,并支持主题令牌(Design Token)定制与 hashId 作用域隔离,接入 ConfigProvider 的主题能力后骨架色可随全局主题联动; - 类型导出:
SkeletonButtonProps、SkeletonInputProps、SkeletonAvatarProps、SkeletonTitleProps、SkeletonProps等类型均从 components/skeleton/index.tsx 导出,便于在<script setup>中做强类型约束(示例 element.vue 中即通过SkeletonButtonProps['size']、SkeletonAvatarProps['shape']约束 ref 类型)。
总结:Skeleton 最佳实践清单
- 首次加载用 Skeleton,刷新加载用 Spin:按官方建议,Skeleton 只适合首次数据加载,让用户提前感知页面结构;
- 用
loading+ 默认插槽做无缝切换:把真实内容放进<a-skeleton :loading="loading">,数据返回后自动替换,避免布局跳动; - 善用对象形式 props:
avatar/title/paragraph传对象即可精确控制形状、尺寸、行数与逐行宽度,而不必自己拼 CSS; - 页面级骨架用组合形态:头像 + 标题 + 段落会被自动编排出协调比例(标题 50%、段落 2 行、末行 61%),直接可用;
- 局部占位用子组件:按钮、输入框、图片等场景优先使用
a-skeleton-button、a-skeleton-input、a-skeleton-image,形态与真实组件对齐; - 开启
active提升感知:需要明确表达"加载中"时给骨架加上流光动画,等待体验更好。
通过本文的 API 表格、官方示例与源码解析,你可以在 ant-design-vue 项目中快速实现从"全页骨架"到"局部元素占位"的完整加载体验。
- 前端
- UI组件
- 设计系统
【免费下载链接】ant-design-vue
🌈 An enterprise-class UI components based on Ant Design and Vue. 🐜
相关推荐
Buzz Welcome 频道 agent 互相回复不止(runaway reply loop)怎么排查?
Buzz Welcome 频道 agent 互相回复不止(runaway reply loop)怎么排查? 如果你在 Buzz 的 Welcome 频道里看到
前端UI组件设计系统Ant Design Skeleton 骨架屏组件全面实战指南:占位组合、子组件、语义化样式与主题定制
Ant Design Skeleton 骨架屏组件全面实战指南:占位组合、子组件、语义化样式与主题定制 Skeleton(骨架屏)是 Ant Design 反馈
前端UI组件设计系统Ant Design Skeleton 骨架屏组件完全指南:占位加载、复合元素与源码实现剖析
Ant Design Skeleton 骨架屏组件完全指南:占位加载、复合元素与源码实现剖析 Skeleton 是 Ant Design 在“内容尚未就绪”阶段
前端UI组件设计系统
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考