图片懒加载

120 阅读1分钟

目的

界面优化,由于图片数量过多,一次性加载完比较耗时,故采用懒加载。

原理

  1. 为了减少图片请求,初始时,将所有的img标签src设置为同一小型图片,这样只有一次请求
  2. 将图片的真实路径绑定在其他属性上如data-url="xxx"
<img data-url="xxx" src="1px.gif" width="100" height="100"/>
  1. 判断滚动事件,当图片进入视野,再替换src的属性值,进行图片加载。

实现

const lazyImg = (height) => {
    var imgs = document.getElementsByTagName("img");
    // 初始化先执行一次
    scrollFn();
    // 监听滚动事件
    window.addEventListener("scroll", scrollFn);
    function scrollFn() {
        var clietH =
            window.innerHeight ||
            document.documentElement.clientHeight ||
            document.body.clientHeight;
        var scrollTop =
            document.documentElement.scrollTop ||
            window.pageYOffset ||
            document.body.scrollTop;
        Array.from(imgs).forEach((item) => {
            let eleTop = item.offsetTop;
            let count = eleTop - (scrollTop + clietH);
            if (count < height) {
                //从data-url中取出真实的图片地址赋值给scr
                item.setAttribute(
                    "src",
                    item.getAttribute("data-url")
                );
            }
        });
    }
    return () => {
        // 移除监听事件
        window.removeEventListener("scroll", scrollFn);
    };
};
const removeLazyImg = lazyImg(100);

使用getBoundingClientRect方法实现:

const lazyImg = (height) => {
    var imgs = document.getElementsByTagName("img");
    // 初始化先执行一次
    scrollFn();
    // 监听滚动事件
    window.addEventListener("scroll", scrollFn);
    function scrollFn() {
        var clietH =
            window.innerHeight ||
            document.documentElement.clientHeight ||
            document.body.clientHeight;
        Array.from(imgs).forEach((item) => {
            let ele = item.getBoundingClientRect();
            ele.top >= 0 &&
                ele.top <= clietH + height &&
                item.setAttribute(
                    "src",
                    item.getAttribute("data-url")
                );
        });
    }
    return () => {
        // 移除监听事件
        window.removeEventListener("scroll", scrollFn);
    };
};
const removeLazyImg = lazyImg(-100);

使用IntersectionObserver实现:

const lazyImg = (height) => {
    var imgs = document.getElementsByTagName("img");
    let io = new IntersectionObserver((entires) => {
        entires.forEach((item) => {
            // 图片元素
            let ele = item.target;
            if (
                item.intersectionRatio > 0 &&
                item.intersectionRatio <= 1
            ) {
                ele.setAttribute(
                    "src",
                    ele.getAttribute("data-url")
                );
            }
        });
    });
    // 给每所有图片都添加进观察器
    Array.from(imgs).forEach((element) => {
        io.observe(element);
    });
};
lazyImg(-100);

参考

【前端】图片懒加载的原理和三种实现方式