Ant Design Skeleton 骨架屏组件完全指南:从基础用法到源码级原理解析
【免费下载链接】ant-designAn enterprise-class UI design language and React UI library项目地址: https://gitcode.com/gh_mirrors/ant/ant-design
Skeleton(骨架屏)是 Ant Design 提供的一组在内容加载完成前渲染的占位图形组件,用于在网络较慢、数据请求耗时较长时给出"内容即将呈现"的视觉反馈,显著缓解用户的等待焦虑。本文将基于当前仓库中 Skeleton 组件文档 及 components/skeleton 目录下的完整源码,系统讲解 Skeleton 的使用场景、全部 API 参数、复合子组件用法,并深入剖析其布局引擎、智能默认值与 Design Token 的底层实现,帮助你在项目中用得对、用得深、用得好看。
何时使用骨架屏
根据官方文档,Skeleton 适用于以下典型场景:
- 网络较慢,需要长时间等待加载处理:接口响应慢、首屏数据请求多时,空白页面会让用户误以为页面故障,骨架屏可以明确告知"内容正在加载"。
- 图文信息内容较多的列表/卡片:例如文章列表、商品卡片、用户信息卡片,用与最终布局一致的占位块,让用户提前感知页面结构。
- 只在第一次加载数据的时候使用:后续数据刷新通常已有缓存或用户已熟悉页面,无需反复展示占位。
- 与 Spin 的关系:Skeleton 可以被 Spin 完全代替,但在可用的场景下,骨架屏能提供比 Spin 更好的视觉效果和用户体验——它预演了真实内容的轮廓,而不是一个孤立的加载图标。
快速上手:基础用法
最简单的用法是直接渲染一个默认的 Skeleton,它会生成一个标题加两行段落的占位结构(见 demo/basic.tsx):
import React from 'react'; import { Skeleton } from 'antd'; const App: React.FC = () => <Skeleton />; export default App;默认情况下 Skeleton 展示:
title默认true,渲染一条标题占位;paragraph默认true,渲染两行段落占位;avatar默认false,不展示头像占位。
想要更接近真实内容的"复杂组合",可以同时开启头像并增加段落行数(见 demo/complex.tsx):
import React from 'react'; import { Skeleton } from 'antd'; const App: React.FC = () => <Skeleton avatar paragraph={{ rows: 4 }} />; export default App;与真实内容无缝切换:loading 与子组件
Skeleton 最核心的使用模式是"占位/真实内容二选一":通过loading属性控制,当loading为true时渲染骨架,为false时直接渲染子组件(见 demo/children.tsx):
import React, { useState } from 'react'; import { Button, Skeleton, Space } from 'antd'; const App: React.FC = () => { const [loading, setLoading] = useState<boolean>(false); const showSkeleton = () => { setLoading(true); setTimeout(() => { setLoading(false); }, 3000); }; return ( <Space direction="vertical" style={{ width: '100%' }} size={16}> <Skeleton loading={loading}> <h4 style={{ marginBottom: 16 }}>Ant Design, 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> </Skeleton> <Button onClick={showSkeleton} disabled={loading}> Show Skeleton </Button> </Space> ); }; export default App;点击按钮后骨架屏展示 3 秒,随后无缝切换为真实内容。这个能力在列表加载中尤其常用,见 demo/list.tsx:把Skeleton包裹在List.Item内,loading为true时展示占位,为false时渲染List.Item.Meta、操作按钮与配图。
loading 判断的源码细节
loading的渲染逻辑在 Skeleton.tsx 中实现,值得注意的判断条件是:
if (loading || !('loading' in props)) { // 渲染骨架占位 ... } return children ?? null;也就是说:只要显式传入了loading且值为false,就渲染子组件;如果不传loading属性,则始终渲染骨架。同时children为空时返回null。从源码结构看,"不传 loading 即永远显示占位"的设计,是为了让 Skeleton 既能当作"纯占位"使用(不包任何子组件),也能当作"条件占位容器"使用(配合 loading 切换)。相关行为在tests/index.test.tsx 中有完整用例覆盖,例如<Skeleton loading={false} />渲染空、<Skeleton loading={false}>{0}</Skeleton>保留子节点0等边界情况。
API 全解:Skeleton 主组件
Skeleton 主组件的属性定义见 Skeleton.tsx 中的 SkeletonProps,与文档 API 表格一一对应:
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| active | 是否展示动画效果 | boolean | false |
| avatar | 是否显示头像占位图 | boolean | SkeletonAvatarProps | false |
| loading | 为 true 时显示占位图,反之直接展示子组件 | boolean | -(不传则始终显示骨架) |
| paragraph | 是否显示段落占位图 | boolean | SkeletonParagraphProps | true |
| round | 为 true 时,段落和标题显示圆角 | boolean | false |
| title | 是否显示标题占位图 | boolean | SkeletonTitleProps | true |
此外源码还支持prefixCls(自定义前缀)、className、rootClassName、style等通用属性。通用属性说明可参考 通用属性文档。
子组件的智能默认值(源码级)
在 Skeleton.tsx 中,avatar、title、paragraph既可以传boolean开关,也可以传对象;传对象时通过getComponentProps直接透传,传布尔值时使用一组随组合关系变化的智能默认值:
- 头像(
getAvatarBasicProps):当"有标题、无段落"时,默认使用size: 'large'、shape: 'square'的方形头像;其他情况默认size: 'large'、shape: 'circle'的圆形头像。 - 标题(
getTitleBasicProps):无头像但有段落时宽度默认为38%;有头像且有段落时宽度默认为50%。 - 段落(
getParagraphBasicProps):无头像或没有标题时,宽度默认为61%;无头像且有标题时行数默认为3,否则默认为2。
这意味着<Skeleton avatar />与<Skeleton avatar paragraph={false} />呈现的头像形态(圆形 vs 方形)是不同的——这正是骨架屏"预演真实布局"设计理念的体现。渲染结构上,Skeleton 使用table布局:头像包裹在${prefixCls}-header,标题与段落包裹在${prefixCls}-content,with-avatar等状态类名由 classNames 按需拼接,同时支持rtl方向。
子元素骨架组件:Skeleton.Button / Avatar / Input / Image / Node
Skeleton 是一个复合组件,源码在 index.tsx 中默认导出,并在 Skeleton.tsx 末尾 挂载了五个静态子组件:Skeleton.Button、Skeleton.Avatar、Skeleton.Input、Skeleton.Image、Skeleton.Node。它们用于模拟具体的界面元素形态,在表单页、个人中心等场景非常实用(见 demo/element.tsx 对应的"按钮/头像/输入框/图像/自定义节点"演示)。
import { Skeleton } from 'antd'; // 模拟按钮 / 头像 / 输入框 / 图片 <Skeleton.Button active /> <Skeleton.Avatar active /> <Skeleton.Input active /> <Skeleton.Image active />SkeletonAvatarProps
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| active | 是否展示动画效果,仅在单独使用头像骨架时生效 | boolean | false |
| shape | 指定头像的形状 | circle|square | -(源码中独立使用时默认circle) |
| size | 设置头像占位图的大小 | number |large|small|default | -(独立使用时默认default) |
SkeletonTitleProps
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| width | 设置标题占位图的宽度 | number | string | - |
SkeletonParagraphProps
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| rows | 设置段落占位图的行数 | number | -(源码中默认2) |
| width | 设置段落占位图的宽度;若为数组则为对应每行的宽度,反之则是最后一行的宽度 | number | string | Array<number | string> | - |
paragraph.width的数组语义在 Paragraph.tsx 的 getWidth 中体现:传数组时按索引取对应行宽度;传单个值时,只有最后一行(rows - 1 === index)应用该宽度,其余行保持 100%。配合 style 中li:last-child:not(:first-child):not(:nth-child(2))默认 61% 的收尾规则,呈现出"段落逐行缩短"的经典文本占位效果。
SkeletonButtonProps
| 属性 | 说明 | 类型 | 默认值 | 版本 |
|---|---|---|---|---|
| active | 是否展示动画效果 | boolean | false | |
| block | 将按钮宽度调整为其父宽度的选项 | boolean | false | 4.17.0 |
| shape | 指定按钮的形状 | circle|round|square|default | - | |
| size | 设置按钮的大小 | large|small|default | - |
SkeletonInputProps
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| active | 是否展示动画效果 | boolean | false |
| size | 设置输入框的大小 | large|small|default | - |
从源码看,SkeletonInputProps还支持block属性(见 Input.tsx),与按钮的block语义一致,将输入框宽度撑满父容器。所有子元素组件都共享一个通用样式引擎,见下节。
源码原理:统一的占位元素引擎 Element
五个子组件内部都基于 Element.tsx 渲染:
size为large/small时拼接-lg/-sm类名,尺寸数值由 CSS Token 的controlHeightLG/controlHeightSM决定;shape为circle/square/round时拼接对应类名;size传入数字时,直接通过内联样式设置width: size; height: size; lineHeight: size + 'px'(见 Element.tsx 的 sizeStyle),实现任意像素尺寸的占位。
各子组件的具体形态由 style/index.ts 中的样式生成函数定义:按钮宽度为controlHeight × 2、输入框宽度为controlHeight × 5、头像与图片的圆形/圆角规则、-block时宽度 100% 等,均以 Design Token 为输入计算得出,保证与真实 Button、Input、Avatar 组件的视觉规格严格对齐。
图片与自定义节点
- Skeleton.Image:内置一张图片占位 SVG(见 Image.tsx 中内联的 path 数据),通过 CSS 类
-image-svg、-image-path控制尺寸与填充色,viewBox 为0 0 1098 1024,无需任何外部资源即可渲染。 - Skeleton.Node:支持通过
children传入任意自定义节点作为占位内容,不传时默认渲染@ant-design/icons的DotChartOutlined图标(见 Node.tsx)。这为"自定义形状占位"提供了扩展入口。
动画效果:active 的底层实现
active属性开启后,占位块会呈现一条光带从左向右扫过的渐变动画。其实现位于 style/index.ts:
- 定义
ant-skeleton-loadingKeyframes,动画从backgroundPosition: 100% 50%移动到0 50%; - 动画背景为
linear-gradient(90deg, gradientFromColor 25%, gradientToColor 37%, gradientFromColor 63%),backgroundSize: 400% 100%; - 动画时长
1.4s、缓动函数ease、无限循环(见genSkeletonColor)。
应用到active状态时,标题、段落行、头像、按钮、输入框、图片等所有占位元素统一套用该动画样式(见 genBaseStyle 中的 active 规则)。
主题变量(Design Token):精细定制骨架屏外观
Skeleton 支持通过 Design Token 定制外观,文档中以<ComponentTokenTable component="Skeleton" />展示,对应的 Token 定义与默认值逻辑在 style/index.ts 的 ComponentToken 与 prepareComponentToken 中:
| Token | 说明 | 默认值来源 |
|---|---|---|
| gradientFromColor | 渐变色起点颜色 | colorFillContent(旧的color已废弃并映射至此) |
| gradientToColor | 渐变色终点颜色 | colorFill(旧的colorGradientEnd已废弃并映射至此) |
| titleHeight | 标题骨架屏高度 | controlHeight / 2 |
| blockRadius | 骨架屏圆角 | borderRadiusSM |
| paragraphMarginTop | 段落骨架屏上间距 | marginLG + marginXXS |
| paragraphLiHeight | 段落骨架屏单行高度 | controlHeight / 2 |
其中color、colorGradientEnd属于废弃 Token,通过deprecatedTokens配置自动映射到新的渐变 Token(见 style/index.ts),升级后无需修改业务代码。
在项目中使用ConfigProvider的theme.components即可定制:
import { ConfigProvider, Skeleton } from 'antd'; <ConfigProvider theme={{ components: { Skeleton: { gradientFromColor: '#f0f0f0', gradientToColor: '#d9d9d9', titleHeight: 24, blockRadius: 8, paragraphMarginTop: 24, paragraphLiHeight: 18, }, }, }} > <Skeleton active avatar paragraph={{ rows: 4 }} /> </ConfigProvider>另外,Skeleton 还支持通过ConfigProvider的skeleton配置项统一注入className与style,该能力在 Skeleton.tsx 中通过ConfigContext读取并合并到最终渲染上,适合做全局骨架屏风格定制。
最佳实践小结
- 首屏加载用骨架、过程反馈用 Spin:首次加载数据时优先考虑
Skeleton,其布局预演带来的体验优于孤立旋转的加载图标。 - 善用 loading + 子组件:用
<Skeleton loading={...}>{真实内容}</Skeleton>包裹列表项或卡片内容,数据到达后自动无缝切换,无需手动控制显隐(参考 demo/list.tsx 与 demo/children.tsx)。 - 用复合子组件精确模拟页面形态:表单页用
Skeleton.Button/Skeleton.Input,个人中心用Skeleton.Avatar,图片流用Skeleton.Image,特殊形状用Skeleton.Node自定义(参考 demo/element.tsx)。 - 按需开启 active 与 round:
active提供呼吸光带动效提升感知,round让标题和段落变成胶囊圆角,配合主题 Token 可融入不同设计体系。 - 深入阅读:完整源码位于 components/skeleton,组件测试见tests/index.test.tsx(覆盖默认渲染、方形头像、round、loading 切换、各子组件尺寸与形状等场景)与tests/image.test.ts,样式 Token 实现见 style/index.ts,可作为二次开发与调试的参考依据。
【免费下载链接】ant-designAn enterprise-class UI design language and React UI library项目地址: https://gitcode.com/gh_mirrors/ant/ant-design
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考