Ant Design Skeleton 组件家族共享 API 深入解析:active 动画与 classNames/styles 语义化定制
components/skeleton/shared/sharedProps.en-US.md 是 Ant Design 官方文档中专门用于沉淀 Skeleton、Skeleton.Avatar、Skeleton.Button、Skeleton.Input、Skeleton.Image、Skeleton.Node 六个占位组件公共属性的 API 参考表,通过 <embed> 机制被 Skeleton 组件文档 的 "Common API" 小节引用。本文以该共享 API 表为主体,结合 Skeleton 家族源码(Skeleton.tsx、Element.tsx、Avatar.tsx、Button.tsx)与语义化 Demo(demo/_semantic.tsx、demo/style-class.tsx),逐一讲解 active、classNames、styles 三个共享属性的默认值、类型约束、语义化 DOM 结构与实现原理,帮助你在"内容加载占位"与"骨架屏组件二次封装"场景中写出更精细的骨架屏。
共享 API 全景表
下表完整摘录自 sharedProps.en-US.md,适用于 Skeleton 及其五个子组件。其中 active 因组件间实现路径不同而不支持全局配置(标记 ×),classNames 与 styles 自 6.0.0 起支持通过 ConfigProvider 组件级配置 进行全局设置:
| Property | Description | Type | Default | Version | Global Config |
|---|---|---|---|---|---|
| active | Show animation effect | boolean | false | - | × |
| classNames | Customize class for each semantic structure inside the Skeleton component. Supports object or function. | Record<SemanticDOM>, string> | (info: { props }) => Record<SemanticDOM>, string> | - | 6.0.0 | 6.0.0 |
| styles | Customize inline style for each semantic structure inside the Skeleton component. Supports object or function. | Record<SemanticDOM>, CSSProperties> | (info: { props }) => Record<SemanticDOM>, CSSProperties> | - | 6.0.0 | 6.0.0 |
与通用公共属性(如
className、style、无障碍相关 props)的说明,可参考 Ant Design 的 Common props 文档;本表仅覆盖 Skeleton 家族组件自有的、语义化定制相关的共享属性。
三个共享属性的逐项解读
active:骨架屏闪烁动画开关
- 默认值:
false - 作用:开启后骨架块会产生呼吸/闪烁的加载动画,向用户传达"内容正在加载中"。
- 实现证据:
- 在组合型 Skeleton.tsx 中,当
active为真时向根节点追加${prefixCls}-active修饰类;同时在渲染头像、标题、段落占位时,动画效果由该根类统一驱动。 - 在独立元素组件中,Avatar.tsx 与 Button.tsx 各自通过
active为包裹层追加${prefixCls}-active;但Skeleton.Avatar独立使用时还受自身active控制(见 index.en-US.md 中 "only valid when used avatar independently" 的注释)。
- 在组合型 Skeleton.tsx 中,当
- 适用建议:加载耗时较长时(如列表、卡片首屏数据)开启动画;可参考官方示例 demo/active.tsx(对应文档 active.md)。Skeleton 中
active的取舍思路是:"Skeleton 本质是加载状态占位,与 Spin 可互相替换,但能提供更好的用户观感"(见 When To Use)。
classNames:为每个语义化结构定制 class
- 类型:支持两种形态——
- 静态对象:
Record<SemanticDOM, string>; - 动态函数:
(info: { props }) => Record<SemanticDOM, string>,可根据当前组件props动态返回 class 映射。
- 静态对象:
- 默认值:
-(不附加任何自定义语义类)。 - 版本:6.0.0 引入,且自该版本起支持全局配置。
- 原理剖析:在 Skeleton.tsx 中,
classNames经由useMergeSemantichook(位于 components/_util/hooks/useMergeSemantic)与上下文中的contextClassNames合并,再逐层下发给avatar、title、paragraph节点,最终通过clsx拼接到语义 DOM 上。Skeleton 支持的语义键为root / header / section / avatar / title / paragraph(类型定义见 Skeleton.tsx),而独立元素(Avatar/Button/Input/Image/Node)仅支持root / content(类型定义见 Element.tsx)。
styles:为每个语义化结构定制内联样式
- 类型:同样支持静态对象
Record<SemanticDOM, CSSProperties>或函数形态(info: { props }) => Record<SemanticDOM, CSSProperties>。 - 默认值:
-。 - 版本:6.0.0 引入并支持全局配置。
- 原理剖析:
styles与style属性在 useMergeSemantic 合并逻辑中被统一处理——style(以及来自上下文的contextStyle)会被视作语义化根节点root的样式来源(useSemanticRootStyle),而styles.avatar、styles.title等则分别注入对应占位节点;同时 Avatar/Button 组件内部会把styles.content透传给底层 Element.tsx 渲染的<span>,因此可以实现"外层盒样式 + 内容块样式"的分层定制。
语义化 DOM(Semantic DOM)结构与定制映射
classNames / styles 的对象键不是随意的 CSS 类名,而必须对应组件暴露的语义化节点。Skeleton 家族的语义化 DOM 分为两层:
Skeleton 组合型组件的六个语义节点
从 Skeleton.tsx 的渲染结构及 demo/_semantic.tsx 的官方标注可见:
root:骨架屏容器根元素,承载表格布局、宽度、动画、圆角等基础样式;header:头部区域,包裹头像占位的布局样式(对应类${prefixCls}-header);section:内容区块,包裹标题与段落的布局样式(对应类${prefixCls}-section);avatar:头像占位元素(由Element渲染);title:标题占位元素;paragraph:段落占位元素。
Element(Avatar/Button/Input/Image/Node)的两个语义节点
独立元素组件在 Avatar.tsx、Button.tsx 中均遵循同一模式:classNames.root / styles.root 作用于外层 <div>(类 ${prefixCls}-element),classNames.content / styles.content 作用于内部由 Element.tsx 渲染的 <span>。完整节点定义与交互式预览见官方 demo/_semantic_element.tsx,其中通过 Segmented 可切换 Avatar、Button、Input、Image、Node 五种元素逐个查看 root/content 语义层。
对象与函数两种形态的使用示例
静态对象形态
参考官方 demo/style-class.tsx,直接声明语义键到样式值的映射:
import { Skeleton } from 'antd';
const classnames = {
root: 'my-skeleton-root',
avatar: 'my-skeleton-avatar',
title: 'my-skeleton-title',
paragraph: 'my-skeleton-paragraph',
};
const styles: React.CSSProperties = {
header: { marginBottom: 8 },
section: { padding: 16 },
};
const App = () => (
<Skeleton classNames={classnames} styles={styles} avatar paragraph={false} />
);
动态函数形态
当需要依据当前 props(例如 loading 状态、是否包含头像)决定语义样式时,可传入 (info: { props }) => Record<SemanticDOM, ...> 形式的函数:
import { Skeleton } from 'antd';
const App = () => (
<Skeleton
avatar
classNames={({ props }) => ({
root: props.loading ? 'skeleton-loading' : 'skeleton-done',
})}
styles={({ props }) => ({
paragraph: { width: props.paragraph ? '100%' : '60%' },
})}
/>
);
全局配置:如何在 ConfigProvider 中统一定制
自 6.0.0 起,classNames 与 styles 已接入 ConfigProvider 的组件级配置通道(component-config)。这一能力在源码中的落点为 Skeleton.tsx:组件通过 useComponentConfig('skeleton') 从 ConfigProvider 上下文读取 classNames / styles / className / style 等默认值,再交由 useMergeSemantic 与本地的 classNames / styles 合并,合并优先级为:context.classNames.root < context.className < 组件 classNames.root < 组件 className < rootClassName(注释见 Skeleton.tsx)。
据此,可在应用根部统一注入各 Skeleton 占位的语义化样式:
import { ConfigProvider, Skeleton } from 'antd';
const App = () => (
<ConfigProvider
componentConfig={{
skeleton: {
classNames: { root: 'app-skeleton' },
styles: { title: { borderRadius: 6 } },
},
}}
>
{/* 应用内所有 Skeleton 自动携带统一语义化样式 */}
<Skeleton active avatar paragraph={{ rows: 4 }} />
</ConfigProvider>
);
需要特别留意的是,active 在共享 API 表中标注为 ×(不支持全局配置),原因从源码路径即可理解:active 的动画行为分散在 Skeleton 根节点与各元素组件各自的条件类拼接中(Skeleton.tsx、Avatar.tsx、Button.tsx),未纳入统一的组件级配置合并链路。如需全局开启动画,应通过 ConfigProvider 的 token/主题方案或封装组件实现。
相关组件单独属性一览
共享 API 之外的组件私有属性见 components/skeleton/index.en-US.md,包括:
- Skeleton 本体:
loading(为 true 时显示骨架屏)、avatar、title、paragraph、round(圆角开关),其中avatar/title/paragraph接受布尔值或对象;传入paragraph={{ rows, width }}、title={{ width }}可精确控制占位行数与宽度。 - Skeleton.Avatar:
shape(circle/square,默认 circle)、size(number | large | medium | small,默认 medium)。 - Skeleton.Button:
block(4.17.0 起支持撑满父容器宽度)、shape(circle/round/square/default)、size。 - Skeleton.Input:
size(large | medium | small)。
在 index.en-US.md 的 "Common API" 小节中,本共享 API 表通过 <embed src="./shared/sharedProps.en-US.md"> 方式复用;中文对照见 sharedProps.zh-CN.md。配合 element.md(演示 Button/Avatar/Input/Image/Node 五种占位元素)与 complex.md(复杂组合布局)等示例,即可覆盖从"单元素占位"到"列表/卡片级复合骨架屏"的全部常见场景。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0629
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python07
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00