Skip to content

Image

Image 是增强型图片组件:在保留原生 img 语义和事件能力的基础上,补齐了加载占位、失败回退、响应式资源协商、裁剪参数拼接、预览交互和状态渲染。

Basic

Size & Fit

通过 aspectRatio 锁定容器比例,配合 fit / position 控制图片裁剪策略,减少布局偏移。

Fallback

主图失败时可先尝试 fallbackSrc,最终再回退到 fallback 节点。

SX Custom

sx 作用于外层容器,可统一控制边框、圆角、阴影、尺寸与比例。

Preview

开启 preview 后支持:

  • 点击图片打开预览
  • 遮罩点击关闭
  • ESC 关闭
  • 滚轮缩放
  • + / - / 0 键盘缩放与重置
  • 预览内拖拽平移(放大后)

Render State

通过 children(state) 可读取组件状态(如 loading/error/loaded)并渲染叠加层。

Responsive Sources

通过 sources + formats + responsiveWidths + loader 输出 <picture>,覆盖媒体条件和格式优先级场景。

OSS Crop

开启 crop 且传入数值 width/height 时,若未传 loader,组件会自动拼接 OSS 裁剪参数。

常见场景

基础展示

用于页面主体、列表项或卡片中直接展示 Image 的默认形态。

状态与数据驱动

当内容来自接口或业务状态时,优先把状态转换为组件 props,再交给 Image 渲染。

样式组合

需要贴近业务页面时,通过 classNameclassstylesx 做局部覆盖。

Usage

tsx
import { Image } from "@ldkj/web-ui";

export function Example() {
  return (
    <Image
      src="/cover.jpg"
      alt="产品封面"
      aspectRatio="16/9"
      fit="cover"
      sizes="(max-width: 768px) 100vw, 640px"
      formats={["avif", "webp"]}
      responsiveWidths={[360, 640, 960, 1360]}
      loader={(src, options) => {
        const params = new URLSearchParams();
        if (options.width) params.set("w", String(options.width));
        if (options.quality) params.set("q", String(options.quality));
        if (options.format) params.set("fmt", options.format);
        return params.size ? `${src}?${params.toString()}` : src;
      }}
      sources={[
        {
          media: "(min-width: 1024px)",
          srcSet: "/cover-desktop.webp 1x, /cover-desktop@2x.webp 2x",
          type: "image/webp",
        },
      ]}
      crop
      width={640}
      height={360}
      fallbackSrc="/cover-fallback.jpg"
      loadingFallback={<div>加载中...</div>}
      fallback={<div>图片加载失败</div>}
      preview
    >
      {({ loading, error }) =>
        loading ? <div>loading...</div> : error ? <div>error</div> : null
      }
    </Image>
  );
}

API

Image 继承原生 img 属性,并通过 forwardRefref 指向内部 img 节点。

属性说明类型默认值
src图片地址string-
alt替代文本string-
fallback最终回退内容React.ReactNode-
fallbackSrc主图失败后的备用地址string-
loadingFallback加载中占位内容React.ReactNode-
fit对应 object-fitReact.CSSProperties["objectFit"]-
position对应 object-positionReact.CSSProperties["objectPosition"]-
aspectRatio外层容器比例number | string-
placeholder占位模式"blur"-
blurDataURL模糊占位背景图string-
retry失败重试次数number0
retryDelay重试延迟(ms)number800
onLoadingChangeloading 状态变更回调(loading: boolean) => void-
loader地址转换函数(src, options) => string-
quality传给 loader 的质量参数number-
format传给 loader 的单图格式参数string-
crop开启默认 OSS 裁剪参数拼接(需数值 width/heightbooleanfalse
sources自定义 <source> 列表{ media?: string; srcSet: string; type?: string; sizes?: string }[]-
formats自动格式候选列表("webp" | "avif")[]-
responsiveWidths配合 loader 生成 w 描述的 srcSetnumber[]-
sizes响应式资源尺寸提示string-
preview是否启用预览booleanfalse
children状态渲染函数(state) => React.ReactNode-
className追加类名string-
class历史类名别名string-
style外层容器内联样式React.CSSProperties-
sx外层容器样式入口SxProps-
onError加载失败回调React.ReactEventHandler<HTMLImageElement>-
...rest其他原生 img 属性透传React.ImgHTMLAttributes<HTMLImageElement>-

行为规则 / 优先级

  1. 主图失败后先走 retry
  2. 重试结束后尝试 fallbackSrc
  3. fallbackSrc 失败后渲染 fallback

说明:fallback 不是第一优先级,而是最终兜底。

资源协商规则

  • 传入 sourcesformats 时,组件渲染 <picture>
  • formats 会基于 src 扩展名推导候选格式资源
  • loader + responsiveWidths 会生成 ... 360w, ... 640w 这类 srcSet
  • sizes 会同时传给 source/img
  • 预览始终基于最终 img src(不直接读取 source 命中项)

Preview 交互与可访问性

  • 弹层使用 role="dialog" + aria-modal="true"
  • 打开预览后聚焦关闭按钮,关闭后焦点回到触发前元素
  • 预览开启时锁定页面滚动
  • 关闭按钮和弹层均提供可访问名称

Notes

  • 内容图必须提供有意义 alt
  • 装饰图使用 alt=""
  • 在卡片/列表中优先设置 aspectRatio + fit="cover",避免 CLS
  • 有 CDN 时优先提供 loader + responsiveWidths + sizes
  • 无 CDN 但使用 OSS 时可直接用 crop + width + height

常见问题

  • formatsdata: / blob: 地址不生效:这类地址不会自动改写扩展名
  • sx/style/className 作用于外层容器,不是 img 本体
  • 传了 loader 后,crop 的默认拼接逻辑会交给 loader 接管

Notes

  • src 变化会自动重置状态,避免旧状态污染新图
  • 默认 loading="lazy"decoding="async",可按需覆盖
  • 开发环境下未传 alt 会输出告警