前端图片懒加载解决方案

135 阅读1分钟

懒加载实现原理: 交叉检查对象
前端图片的懒加载包括两类:图片、背景图
代码示例: react

step1: 定义观察器

let lazyImageObserver = null;
if ('IntersectionObserver' in window) {
  let _lazyImageObserver = new IntersectionObserver(function (entries, observer) {
    entries.forEach(function (entry) {
      if (entry.isIntersecting) {
        let lazyImage = entry.target;
        let classList = [].slice.call(lazyImage.classList);
        //处理背景图片
        if (classList.includes('lazy-background')) {
          lazyImage.classList.add('visible');
          lazyImageObserver.unobserve(lazyImage);
        }
        //处理图片
        if (lazyImage.dataset.src) {
          lazyImage.src = lazyImage.dataset.src;
          lazyImage.classList.remove('lazy');
          lazyImageObserver.unobserve(lazyImage);
        }
      }
    });
  });
  lazyImageObserver = _lazyImageObserver;
}
export { lazyImageObserver };

step2: 懒加载实现

懒加载图片组件

/**
 * params: 需要懒加载的图片元素;
 * 原理: 给图片设置data-src="xxx" 当图片元素处于可视窗口时 将data-src赋值给src 实现图片的动态加载。
 */
import { lazyImageObserver } from 'initLazyImgObserver';
const lazyImg = (lazyImage) => {
  if (lazyImageObserver) {
    lazyImageObserver.observe(lazyImage);
  } else {
    if (lazyImage.dataset.src) {
      lazyImage.src = lazyImage.dataset.src;
      lazyImage.classList.remove('lazy');
    }
  }
};
export default lazyImg;

自定义hooks实现懒加载背景图

/****
 *
 * 背景图片懒加载
 *  1.背景图片懒加载 给目标元素加一个.lazy-background类并将背景图片url通过.visible赋值
 *  2.update:boolean————如果页面元素更新之后需要重新进行懒加载图片的收集,则需要传update参数
 */
import { useEffect } from 'react';
import { lazyImageObserver } from 'utils/initLazyImgObserver';
const collectLazyElement = () => {
  var Backgrounds = [].slice.call(document.querySelectorAll('.lazy-background'));
  if (lazyImageObserver) {
    Backgrounds.forEach(function (lazyBgImage) {
      lazyImageObserver.observe(lazyBgImage);
    });
  } else {
    Backgrounds.forEach(function (lazyBgImage) {
      const target = document.querySelector(lazyBgImage);
      target.classList.add('visible');
    });
  }
};
export default (props) => {
  const toUpdate = props?.update;
  useEffect(() => {
    collectLazyElement();
  }, []);
  useEffect(() => {
    toUpdate && collectLazyElement();
  }, [toUpdate]);
};

step3: 懒加载使用

图片懒加载使用——通过ref获取图片dom元素

import lazyImg from 'lazyImg';
const ScrollImg = (props) => {
  const { src: imgSrc, alt = '', ...reset } = props;
  const lazyImgRef = useRef();
  useEffect(() => {
    lazyImg(lazyImgRef.current);
  }, [imgSrc]);

  return <img ref={lazyImgRef} className="lazy" data-src={imgSrc} alt={alt} {...reset} />;
};
export default ScrollImg;

背景懒加载使用 ——通过给dom元素设置类名"lazy-background" 绑定需要观察的元素并给元素设置背景图,当该dom元素位于视口之外时不显示,位于视口时增加"visible"类 显示元素。

import useLazyBgImg from 'useLazyBgImg';
const BgLazy = () => {
  useLazyBgImg();
  return (
    <div className="lazy-background" />
  );
};

export default QuickStart;