You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React中实现所有图片的懒加载?无需逐个添加代码

React全局图片懒加载实现方案

下面是几种不用逐张图片写懒加载代码的全局实现方案:

1. 自定义全局复用懒加载组件

创建一个通用的<LazyImage>组件,之后所有图片都用这个组件替代原生<img>,一次封装全局复用:

import { useState, useEffect, useRef } from 'react';

const LazyImage = ({ src, alt, placeholder = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==', ...props }) => {
  const [imageSrc, setImageSrc] = useState(placeholder);
  const imgRef = useRef(null);

  useEffect(() => {
    const observer = new IntersectionObserver((entries) => {
      entries.forEach(entry => {
        if (entry.isIntersecting) {
          setImageSrc(src);
          observer.unobserve(entry.target);
        }
      });
    }, { threshold: 0.1 });

    if (imgRef.current) observer.observe(imgRef.current);
    return () => imgRef.current && observer.unobserve(imgRef.current);
  }, [src]);

  return (
    <img
      ref={imgRef}
      src={imageSrc}
      alt={alt}
      {...props}
      style={{ objectFit: 'cover', minHeight: '150px', ...props.style }}
    />
  );
};

export default LazyImage;

如果觉得手动替换现有<img>麻烦,可以通过项目配置(比如Webpack别名、Babel插件)将原生img标签全局映射到这个组件。

2. 全局注入原生懒加载属性

现代浏览器支持原生loading="lazy"属性,直接在根组件中全局给所有图片添加该属性,无需修改现有组件:

import { useEffect } from 'react';

function App() {
  useEffect(() => {
    // 处理已存在的图片
    const updateImgs = () => {
      document.querySelectorAll('img:not([loading])').forEach(img => {
        // 排除首屏图片,可根据类名或位置判断
        if (!img.classList.contains('no-lazy')) {
          img.setAttribute('loading', 'lazy');
        }
      });
    };

    updateImgs();

    // 监听动态添加的图片
    const observer = new MutationObserver(mutations => {
      mutations.forEach(mutation => {
        mutation.addedNodes.forEach(node => {
          if (node.tagName === 'IMG' && !node.hasAttribute('loading') && !node.classList.contains('no-lazy')) {
            node.setAttribute('loading', 'lazy');
          }
        });
      });
    });

    observer.observe(document.body, { childList: true, subtree: true });
    return () => observer.disconnect();
  }, []);

  // 根组件其余内容
  return <div className="app">{/* ... */}</div>;
}

注意:原生懒加载对首屏内的图片、小尺寸图片可能不生效,需根据需求添加排除规则。

3. 全局封装懒加载Hook

写一个通用Hook处理懒加载逻辑,再封装成全局可用的图片组件:

import { useState, useEffect, useRef } from 'react';

// 通用懒加载Hook
const useLazyLoad = (src, placeholder) => {
  const [loadedSrc, setLoadedSrc] = useState(placeholder);
  const ref = useRef(null);

  useEffect(() => {
    const observer = new IntersectionObserver(entries => {
      if (entries[0].isIntersecting) {
        setLoadedSrc(src);
        observer.unobserve(entries[0].target);
      }
    });

    if (ref.current) observer.observe(ref.current);
    return () => ref.current && observer.unobserve(ref.current);
  }, [src]);

  return [ref, loadedSrc];
};

// 封装成全局图片组件
const LazyImg = ({ src, alt, placeholder, ...props }) => {
  const [ref, loadedSrc] = useLazyLoad(src, placeholder || 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==');
  return <img ref={ref} src={loadedSrc} alt={alt} {...props} />;
};

额外注意事项

  • 布局稳定:给图片设置固定宽高或用padding-top比例占位,避免加载时布局偏移。
  • 降级处理:对不支持IntersectionObserver的旧浏览器,引入intersection-observer polyfill。
  • 首屏优化:首屏内的图片不需要懒加载,可通过类名(如no-lazy)在全局逻辑中排除。

内容的提问来源于stack exchange,提问作者mntymccass

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 12:01:02