Ant Design Image 图片组件:加载占位、容错处理与全屏预览的完整实践指南
本文以 ant-design 仓库中 components/image/index.zh-CN.md 为骨架,结合
Image/Image.PreviewGroup的真实源码(index.tsx、PreviewGroup.tsx)、hooks 与 style 进行验证与纵深扩充,帮助你把这套"可预览的图片"方案真正用起来。
导读
Image 是 Ant Design 中用于展示图片的组件,核心能力是"可预览":用户既能以普通 <img> 的方式展示单张图片,也能点击图片弹出全屏预览浮层进行缩放、旋转、翻转、平移与前后切换,还可以借助 Image.PreviewGroup 实现多图相册式的浏览体验。针对"大图加载中"与"加载失败"两个高频场景,组件分别提供渐进加载占位(含水墨渐变动画与进度条)和**容错兜底图(fallback)**能力。读完本文,你将掌握 Image 从基础展示到全屏预览、再到语义化定制样式与设计 Token 的完整配置方法,并能结合源码理解这些能力在底层是如何被组装起来的。
何时使用 Image
官方文档给出两条最基本的适用场景:
- 需要展示图片时使用,例如商品图、头像、内容配图等;
- 加载显示大图或加载失败时做容错处理,例如图片尺寸较大、网络不佳或资源地址失效时给出过渡占位或兜底图。
它继承原生 <img> 的大部分属性(src、width、height、alt、crossOrigin 等),因此已有 HTML 图片使用经验的开发者迁移成本很低。在 ant-design 仓库中,组件实现位于 components/image 目录,主体逻辑(index.tsx)是基于底层库 @rc-component/image 的 RcImage 进行的二次封装,你可以把它理解为"原生图片能力 + Ant Design 主题样式 + 更丰富的预览交互"的组合。
基础展示与容错:从一张图开始
基本用法
最基础的使用方式与原生 <img> 几乎一致:
import { Image } from 'antd';
const App = () => (
<Image
width={200}
src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"
/>
);
export default App;
对应的完整演示见 basic.tsx。默认情况下,preview 为 true,点击图片即可进入预览模式;若希望图片不可预览,将 preview={false} 传入即可。
从实现上看,index.tsx 把 prefixCls、classNames、styles、fallback、placeholder 等 props 解析后统一转交给底层 RcImage,并借助 useComponentConfig('image') 读取 ConfigProvider 上下文中的图片级全局配置(如全局 fallback、预览配置、classNames/styles),实现"局部配置优先、上下文配置兜底"的合并策略。
加载失败容错:fallback
当 src 指向的资源加载失败(例如地址错误、CDN 挂了)时,fallback 会接管展示一张兜底图。fallback 自 5.28.0 起支持配置,类型为图片地址字符串:
import { Image } from 'antd';
const App = () => (
<Image
width={200}
height={200}
src="error" // 一个注定加载失败的地址
fallback="data:image/png;base64,iVBORw0KGgo..." // 兜底占位图
/>
);
export default App;
演示见 fallback.tsx。在 index.tsx 中可以看到 mergedFallback 的合并逻辑:
const mergedFallback: RcImageProps['fallback'] = fallback ?? contextFallback;
即组件自身传入的 fallback 优先,未传则回落到 ConfigProvider 中通过 image 组件配置项设置的全局 fallback(contextFallback)。这一设计让业务方可以在入口处统一配置"全局图片兜底地址",而局部仍可单独覆盖。
渐进加载与加载占位:placeholder
针对大图加载、或等待后端生成图片等场景,placeholder 提供了占位层 + 进度可视化能力。它是文档中引入的一类新配置对象,类型为 PlaceholderType:
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|---|---|---|---|---|
| progress | 进度配置,设置为 true 显示渐变动画,设置 { percent: number } 显示进度,render 自定义渲染 |
boolean | ImageProgressConfig | - |
而 placeholder 本身既可以是普通的 React.ReactNode(此时作为一个视觉占位层叠加在图片上),也可以是形如 { progress: ... } 的配置对象。源码 usePlaceholderConfig.ts 中通过 isPlaceholderConfig(判断是否为普通对象且非 ReactElement)来区分这两种形态,并归一化 progress:
placeholder.progress === true:进入"无具体进度、纯渐变动画"的水墨加载态;placeholder.progress === { percent, render }:显示带数值进度条的加载态,并可自定义渲染;placeholder为 ReactNode 且未提供src时,它会被当作覆盖层渲染(见 index.tsx)。
四种典型形态在一个演示中同时呈现(见 placeholder.tsx):
import { Image } from 'antd';
const App = () => (
<>
{/* 1. 无进度数值:纯水墨渐变动画 */}
<Image width={200} height={200} placeholder={{ progress: true }} />
{/* 2. 自定义渲染:用文案替换默认进度 UI */}
<Image
width={200}
height={200}
placeholder={{ progress: { render: () => 'loading...' } }}
/>
{/* 3. 静态指定 50% 进度 */}
<Image width={200} height={200} placeholder={{ progress: { percent: 50 } }} />
{/* 4. 自定义渲染 + 保留默认进度条与百分比 */}
<Image
width={200}
height={200}
placeholder={{
progress: {
percent: 75,
render: (progress, p) => (
<>
{progress}
<div style={{ marginTop: 8 }}>Generating {p}%</div>
</>
),
},
}}
/>
</>
);
export default App;
其中 "Generate" 示例演示了真实业务中"等待 AI 生图/上传完成"的交互:在图片尚未就绪时先渲染带进度条与文案的占位,生成完成后再切换到真实 src。progress.render 的两个入参分别为默认进度 UI 和 0~100 的百分比数值(见 ImageProgressConfig):
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|---|---|---|---|---|
| percent | 进度值 | number | - | |
| render | 自定义渲染,接收默认的进度 UI 和百分比 | (progress: React.ReactNode, percent: number) => React.ReactNode | - |
当 progress 配置存在(无论是否带数值),组件会走 Progress.tsx 单独渲染进度层而非底层 RcImage(见 index.tsx)。这个自研的 Progress 值得注意:
- 内部包含两层"水墨墨迹"(
progress-ink-1/progress-ink-2,配合伪元素共五层径向渐变动画),营造类似水彩晕染的加载氛围,样式实现在 style/index.ts 的genImageProgressStyle; - 提供
rail(轨道)与indicator(百分比文字)两个语义节点,通过 CSS 变量--progress-percent控制轨道填充宽度,并对 percent 做了Math.max(0, Math.min(100, Math.round(...)))的钳制; - 无障碍方面:有百分比时输出
role="progressbar"及aria-valuemin/valuemax/valuenow,无百分比时输出role="status"+aria-live="polite"的 Loading 提示(见 Progress.tsx)。
全屏预览:单图能力全景
预览如何工作
Image 默认点击图片即可打开全屏预览。preview 属性是预览的总开关与配置入口,false 时禁用;传入对象时则精细控制预览行为:
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|---|---|---|---|---|
| actionsRender | 自定义工具栏渲染 | (originalNode: React.ReactElement, info: ToolbarRenderInfoType) => React.ReactNode | - | |
| closeIcon | 自定义关闭 Icon | React.ReactNode | - | |
| cover | 自定义预览遮罩(覆盖在缩略图上、用于提示"可点击预览"的浮层) | React.ReactNode | CoverConfig | - | CoverConfig v6.0 开始支持 |
| focusTrap | 预览打开时是否在预览内捕获焦点 | boolean | true | 6.4.0 |
| 关闭预览时销毁子元素,已移除,不再支持 | boolean | false | ||
| 强制渲染预览图,已移除,不再支持 | boolean | - | ||
| getContainer | 指定预览挂载的节点,但依旧为全屏展示,false 为挂载在当前位置 |
string | HTMLElement | (() => HTMLElement) | false | - | |
| imageRender | 自定义预览内容 | (originalNode: React.ReactElement, info: { transform: TransformType, image: ImgInfo }) => React.ReactNode | - | |
| mask | 预览遮罩效果 | boolean | { enabled?: boolean, blur?: boolean, closable?: boolean } | true | mask.closable: 6.4.0 |
缩略图遮罩类名,请使用 classNames.cover 替换 |
string | - | ||
| maxScale | 最大缩放倍数 | number | 50 | |
| minScale | 最小缩放倍数 | number | 1 | |
| movable | 预览图片大于视口时是否可拖拽移动 | boolean | true | |
| open | 是否显示预览 | boolean | - | |
| rootClassName | 预览图的根 DOM 类名,会同时作用在图片和预览层最外侧 | string | - | |
| scaleStep | 1 + scaleStep 为缩放放大的每步倍数 |
number | 0.5 | |
| src | 自定义预览 src | string | - | |
| styles | 自定义语义化结构样式 | Record<SemanticDOM, CSSProperties> | - | |
| wheel | 是否启用鼠标滚轮缩放 | boolean | true | 6.6.0 |
自定义工具栏,请使用 actionsRender 替换 |
(originalNode: React.ReactElement, info: Omit<ToolbarRenderInfoType, 'current' | 'total'>) => React.ReactNode | - | ||
是否显示,请使用 open 替换 |
boolean | - | ||
| onOpenChange | 预览打开状态变化的回调 | (visible: boolean) => void | - | |
| onTransform | 预览图 transform 变化的回调 | { transform: TransformType, action: TransformAction } | - | |
当 visible 发生改变时的回调,请使用 onOpenChange 替换 |
(visible: boolean, prevVisible: boolean) => void | - |
几个使用要点:
- 受控预览:通过
open+onOpenChange即可把"是否打开预览"交给业务状态管理,对应演示见 controlled-preview.tsx; - 自定义预览图片来源:缩略图与全屏大图地址不一致(例如缩略图是压缩图、预览需原图)时,用
preview={{ src: 'https://.../full.png' }}指定独立预览地址,见 previewSrc.tsx; - 交互能力默认全开:滚轮缩放(
wheel,6.6.0 起可关闭)、拖拽移动(movable)、缩放区间(minScale: 1~maxScale: 50)、每步缩放倍率1 + scaleStep(默认 0.5,即每步放大 1.5 倍); - 遮罩语义:
mask控制的是打开预览时背景遮罩的显示效果(enabled是否展示、blur是否加 4px 高斯模糊、closable点击遮罩是否可关闭);而cover控制的是缩略图悬浮时出现的"预览"提示浮层,二者不要混淆,相关演示见 mask.tsx 与 preview-mask.tsx; - 层级与容器:
getContainer可指定预览渲染挂载节点,但视觉上仍是全屏展示;传入false时预览将挂载在当前位置(内嵌预览,用于做引导型/局部预览)。预览浮层的 z-index 并非写死,而是在 useMergedPreviewConfig.ts 中通过useZIndex('ImagePreview', ...)按规则叠加,最终值与zIndexPopupToken 关联。
在配置解析层面,usePreviewConfig.ts 完成了新旧 API 的归一与降级告警:当传入 visible 时自动映射到 open、onVisibleChange 映射到 onOpenChange、toolbarRender 映射到 actionsRender,rootClassName/maskClassName 分别提示改用 classNames.root/classNames.cover;对已移除的 forceRender、destroyOnClose 以及被废弃的 mask ReactNode 用法,在开发环境下通过 devUseWarning 输出对应告警。仓库对应测试见 tests/deprecated.test.tsx。
自定义预览内容与变换信息
预览浮层中可被业务完全接管的两处:
imageRender:自定义预览内容本身,会收到变换状态(transform)与图片信息(image),可据此叠加水印、标注、局部放大等能力,演示见 imageRender.tsx 与 preview-imgInfo.tsx;actionsRender:自定义底部工具栏。传入的info: ToolbarRenderInfoType内含默认图标集icons、全部操作回调actions以及当前变换/计数信息,见下节 Interface。
预览整体还会把用户对图片的操作持续同步出去:onTransform 会在每次缩放、旋转、翻转、拖拽后回调,携带 transform 与触发动作 action,适合做"操作埋点"或"将变换同步到业务图层"。
多图预览与相册模式:Image.PreviewGroup
当页面存在一组相关图片(如商品图集、聊天中的多张图)时,应使用 Image.PreviewGroup。它负责在两两关联的 Image 之间建立"同一预览序列"的关系——任何一张被点击,都从该序列的对应索引开始全屏预览,并支持左右切换。
两种组织方式
方式一:直接包裹子 Image。序列顺序即子组件声明顺序,可同时监听切换事件,见 preview-group.tsx:
import { Image } from 'antd';
const App = () => (
<Image.PreviewGroup
preview={{
onChange: (current, prev) => console.log(`current index: ${current}, prev index: ${prev}`),
}}
>
<Image width={200} src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg" />
<Image width={200} src="https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg" />
</Image.PreviewGroup>
);
export default App;
方式二:items 相册模式。当缩略区只展示一张"入口图"、但预览序列包含多张大图时使用,见 preview-group-visible.tsx:
import { Image } from 'antd';
const App = () => (
<Image.PreviewGroup
items={[
'https://gw.alipayobjects.com/zos/antfincdn/LlvErxo8H9/photo-1503185912284-5271ff81b9a8.webp',
'https://gw.alipayobjects.com/zos/antfincdn/cV16ZqzMjW/photo-1473091540282-9b846e7965e3.webp',
'https://gw.alipayobjects.com/zos/antfincdn/x43I27A55%26/photo-1438109491414-7198515b166b.webp',
]}
>
<Image width={200} src="https://gw.alipayobjects.com/zos/antfincdn/LlvErxo8H9/photo-1503185912284-5271ff81b9a8.webp" />
</Image.PreviewGroup>
);
export default App;
items 的元素既可以是字符串 src,也可以是 { src, crossOrigin, ... } 形式的对象。在 PreviewGroup.tsx 的实现中,PreviewGroup 复用了与 Image 完全一致的语义化 classNames/styles 合并、上下文预览配置合并(useMergedPreviewConfig)以及前缀类名派生,并把 RTL 方向处理注入到上/下一张的箭头图标里(direction === 'rtl' 时左右箭头互换,见 PreviewGroup.tsx)。
PreviewGroup 顶层属性
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|---|---|---|---|---|
| classNames | 用于自定义组件内部各语义化结构的 class,支持对象或函数 | Record<SemanticDOM, string> | (info: { props }) => Record<SemanticDOM, string> | - | |
| fallback | 加载失败容错地址 | string | - | |
| items | 预览数组 | string[] | { src: string, crossOrigin: string, ... }[] | - | |
| preview | 预览参数,为 false 时禁用 |
boolean | PreviewGroupType | true |
PreviewGroupType(组内预览配置)
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|---|---|---|---|---|
| actionsRender | 自定义工具栏渲染 | (originalNode: React.ReactElement, info: ToolbarRenderInfoType) => React.ReactNode | - | |
| closeIcon | 自定义关闭 Icon | React.ReactNode | - | |
| countRender | 自定义预览计数内容 | (current: number, total: number) => React.ReactNode | - | |
| focusTrap | 预览打开时是否在预览内捕获焦点 | boolean | true | 6.4.0 |
| current | 当前预览图的 index | number | - | |
| 强制渲染预览图,已移除,不再支持 | boolean | - | ||
| getContainer | 指定预览挂载的节点,但依旧为全屏展示,false 为挂载在当前位置 |
string | HTMLElement | (() => HTMLElement) | false | - | |
| imageRender | 自定义预览内容 | (originalNode: React.ReactElement, info: { transform: TransformType, image: ImgInfo, current: number }) => React.ReactNode | - | |
| mask | 预览遮罩效果 | boolean | { enabled?: boolean, blur?: boolean, closable?: boolean } | true | mask.closable: 6.4.0 |
缩略图遮罩类名,请使用 classNames.cover 替换 |
string | - | ||
| minScale | 最小缩放倍数 | number | 1 | |
| maxScale | 最大放大倍数 | number | 50 | |
| movable | 预览图片大于视口时是否可拖拽移动 | boolean | true | |
| open | 是否显示预览 | boolean | - | |
预览图根 DOM 类名,会同时作用在图片和预览层最外侧,请使用 classNames.root 替换 |
string | - | ||
| styles | 自定义语义化结构样式 | Record<SemanticDOM, CSSProperties> | - | |
| wheel | 是否启用鼠标滚轮缩放 | boolean | true | 6.6.0 |
| scaleStep | 1 + scaleStep 为缩放放大的每步倍数 |
number | 0.5 | |
自定义工具栏,请使用 actionsRender 替换 |
(originalNode: React.ReactElement, info: ToolbarRenderInfoType) => React.ReactNode | - | ||
是否显示,请使用 open 替换 |
boolean | - | ||
| onOpenChange | 预览打开状态变化回调,额外携带当前预览图索引 | (visible: boolean, info: { current: number }) => void | - | |
| onChange | 切换预览图的回调 | (current: number, prevCurrent: number) => void | - | |
| onTransform | 预览图 transform 变化的回调 | { transform: TransformType, action: TransformAction } | - | |
当 visible 发生改变时的回调,请使用 onOpenChange 替换 |
(visible: boolean, prevVisible: boolean, current: number) => void | - |
与单图 PreviewType 相比,组的预览配置多出了三类特有内容:
current:初始/受控的当前图片索引,可实现"从第 N 张开始预览";countRender(current, total):自定义右下角"2/8"式的计数文案,见 preview-group-top-progress.tsx(该演示同时展示了预览顶部进度/计数的定制);onOpenChange的回调额外携带{ current }(当前图片索引),onChange则专注于切换事件。
嵌套预览也是被官方支持并在 nested.tsx 中演示的场景:在预览内容内部再次渲染带预览的图片时,内层预览会独立工作,不会被外层序列错误接管。
自定义工具栏:actionsRender 与接口全解
文档将工具栏相关的可扩展类型统一定义在 Interface 章节,它们正是 actionsRender、imageRender 等渲染函数的入参契约:
TransformType
预览对图片施加的所有变换,最终都被归一化为如下结构(x/y 为偏移量):
interface TransformType {
x: number;
y: number;
rotate: number;
scale: number;
flipX: boolean;
flipY: boolean;
}
TransformAction
onTransform 回调中的 action 字段,标识是哪种操作触发了本次变换:
type TransformAction =
| 'flipY' // 垂直翻转
| 'flipX' // 水平翻转
| 'rotateLeft' // 逆时针旋转
| 'rotateRight' // 顺时针旋转
| 'zoomIn' // 放大
| 'zoomOut' // 缩小
| 'close' // 关闭预览
| 'prev' // 上一张
| 'next' // 下一张
| 'wheel' // 滚轮缩放
| 'doubleClick' // 双击
| 'move' // 拖拽移动
| 'dragRebound' // 拖拽回弹
| 'reset'; // 复位
ToolbarRenderInfoType
actionsRender 的回调入参,包含默认图标、全部操作触发函数与当前状态。注意 onActive 为 5.21.0 之后支持(用于组内跳转指定索引),onReset 为 5.17.3 之后支持:
interface ToolbarRenderInfoType {
icons: {
flipYIcon: React.ReactNode;
flipXIcon: React.ReactNode;
rotateLeftIcon: React.ReactNode;
rotateRightIcon: React.ReactNode;
zoomOutIcon: React.ReactNode;
zoomInIcon: React.ReactNode;
};
actions: {
onActive?: (index: number) => void; // 5.21.0 之后支持
onFlipY: () => void;
onFlipX: () => void;
onRotateLeft: () => void;
onRotateRight: () => void;
onZoomOut: () => void;
onZoomIn: () => void;
onReset: () => void; // 5.17.3 之后支持
onClose: () => void;
};
transform: TransformType;
current: number;
total: number;
image: ImgInfo;
}
这些默认操作图标在 PreviewGroup.tsx 中集中定义(翻转共用 SwapOutlined,仅通过 rotate 区分方向),并以 memoizedIcons 注入底层。参考 toolbarRender.tsx 的用法:在 actionsRender 中拿到 actions 后可自定义按钮,例如只保留"旋转 + 缩放 + 关闭"并换掉图标。
ImgInfo
imageRender / actionsRender 中拿到的图片描述信息,配合 alt、宽高实现水印或按比例标注:
interface ImgInfo {
url: string;
alt: string;
width: string | number;
height: string | number;
}
CoverConfig
preview.cover 除了可直接传 ReactNode 作为自定义预览遮罩内容外,从 v6.0 起还支持对象形态,用于控制遮罩内容与位置:
type CoverConfig = {
coverNode?: React.ReactNode; // 自定义遮罩元素
placement?: 'top' | 'bottom' | 'center'; // 设置预览遮罩显示的位置
};
遮罩元素默认铺满整图、悬浮时淡入(透明度过渡),若想改成"顶部条"式提示,用 placement: 'top' 即可;style 层面对应 cover-top / cover-bottom / 默认居中三类定位,实现在 style/index.ts。相关演示见 coverPlacement.tsx。
语义化结构与样式定制(Semantic DOM)
Image 从 v6.0.0 开始支持语义化定制:通过 classNames 与 styles 精准定位组件内部的每个关键 DOM,且二者都支持对象或函数形态(函数接收 { props },可依据当前 props 动态返回),对函数形态与合并细节可参考 _util 层的 useMergeSemantic 实现。完整的语义节点清单定义在 index.tsx 中,并在 demo/_semantic.tsx 中有可视化演示:
| 语义节点 | 对应 DOM 结构 | 说明 |
|---|---|---|
root |
缩略图根元素 | 相对定位、行内块布局 |
image |
<img> 本体 |
宽度、高度与垂直对齐 |
cover |
悬浮预览提示遮罩 | 绝对定位、半透明黑底、悬停淡入 |
placeholder |
占位层 | 其中 placeholder.progress 可继续细分 root/content/rail/indicator(见 Progress.tsx) |
popup.root |
预览浮层根元素 | fixed 定位与 z-index |
popup.mask |
预览背景遮罩 | 半透明背景,支持 blur |
popup.body |
预览内容容器 | flex 居中 |
popup.footer |
预览页脚 | 底部计数等区域 |
popup.actions |
操作工具栏 | 旋转/缩放等按钮组 |
popup.close |
关闭按钮 | 6.4.0 起可单独定制 |
用法示例(配合 6.0 起支持的 style-class.tsx):
<Image
src="..."
classNames={{
root: 'my-image-root',
cover: 'my-image-cover',
popup: { root: 'my-preview-root', mask: 'my-preview-mask' },
}}
styles={{
image: { borderRadius: 8 },
popup: { actions: { background: 'rgba(0,0,0,0.3)' } },
}}
/>
对应底层样式拆分也很清晰:组件 CSS 由 style/index.ts 中的 genImageStyle(基础布局与内置占位底纹)、genImageCoverStyle(cover 遮罩)、genImageProgressStyle(水墨进度层)、genImagePreviewStyle(预览浮层全量样式)与 genPreviewMotion(淡入缩放动效)共同生成。参考演示 component-token.tsx 可看到通过 styles/Token 组合定制组件视觉的完整代码。
主题变量(Design Token)
Image 同样遵循 antd 的 Design Token 体系,可将下述 Token 置于主题中整体调节。Token 名称、语义与默认值均来自 style/index.ts 的 ComponentToken 接口与 prepareComponentToken:
| Token | 说明 | 默认值(来自 prepareComponentToken) |
|---|---|---|
zIndexPopup |
预览浮层 z-index | token.zIndexPopupBase + 80 |
previewOperationSize |
预览操作图标大小 | token.fontSizeIcon * 1.5 |
previewOperationColor |
预览操作图标颜色 | 白色叠 0.65 透明度 |
previewOperationHoverColor |
预览操作图标悬浮颜色 | 白色叠 0.85 透明度 |
previewOperationColorDisabled |
预览操作图标禁用颜色 | 白色叠 0.25 透明度 |
progressAnimationDuration |
加载水墨动画基础时长 | '3s'(墨迹层通过 calc(... + 2s) 等方式错峰) |
通过 <ComponentTokenTable component="Image"> 渲染出的 Token 文档即在 index.zh-CN.md 的"主题变量(Design Token)"章节。例如希望弹层层级更高,可配置 theme={{ components: { Image: { zIndexPopup: 2000 } } } }。
全局配置与常见坑位提示
- ConfigProvider 全局配置:
fallback(5.28.0 起)、preview.closeIcon(5.14.0 起)、preview.mask(6.0.0 起)、preview.mask.closable(6.4.0 起)等均可通过ConfigProvider的image组件级配置统一下发,实现与当前组件 props 的自动合并。详见 config-provider/index.zh-CN.md。其他图片通用属性(alt、width、height、onError等原生img属性)请参考 Ant Design 通用属性文档。 - onError 回调:图片加载失败时触发
(event: Event) => void,可在此埋点或做业务降级(配合fallback展示兜底图)。 - 版本敏感点:文档中已用删除线标注
forceRender、destroyOnClose不再支持,visible/onVisibleChange/toolbarRender/rootClassName/maskClassName属废弃写法。升级到新版本时建议统一迁移到open/onOpenChange/actionsRender/classNames.*,开发环境下控制台也会给出对应弃用提示(见 usePreviewConfig.ts)。 - 无障碍:语义结构覆盖相对完整,仓库为其准备了独立的 a11y.test.ts 测试;若你自定义预览工具栏,请保留键盘可达与焦点管理语义,预览打开时默认启用
focusTrap(6.4.0)。
小结
| 场景 | 推荐 API | 参考实现 |
|---|---|---|
| 基础展示 / 不可点击预览 | <Image preview={false} /> |
index.tsx |
| 大图渐进加载 / 生成中占位 | placeholder={{ progress }} |
placeholder.tsx、Progress.tsx |
| 加载失败兜底 | fallback + onError |
fallback.tsx |
| 多图切换预览 | <Image.PreviewGroup> |
preview-group.tsx |
| 单入口 + 相册序列 | <Image.PreviewGroup items={[...]}> |
preview-group-visible.tsx |
| 受控打开预览 | preview={{ open, onOpenChange }} |
controlled-preview.tsx |
| 替换工具栏 / 预览内容 | actionsRender / imageRender |
toolbarRender.tsx、imageRender.tsx |
| 精确改样式 | classNames / styles / Design Token |
_semantic.tsx、style/index.ts |
围绕 Image 的 16 个官方示例(从 basic.tsx 到 preview-imgInfo.tsx)都位于 components/image/demo,可以直接作为从"展示一张图"到"完整图片浏览器"的进阶路线图。无论你只是需要一张带容错的商品图,还是要构建类似图片墙 + 全屏画廊的产品体验,Image 都能在一条组件链路里完成闭环。
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