<img src="default.jpg" data-src="http://www.xxx.com/target.jpg" /></img>

1. IntersectionObserver

这是浏览器内置的一个 API,实现了监听 window 的 scroll 事件、判断是否在视口中以及节流三大功能。

let imgs = document.getElementsByTagName("img");

const observer = new InteractionObserver(changes => {
    // changes 是被观察的元素集合
    for(let i = 0; i < changes.length; i++) {
        let change = changes[i];
        // 通过 isIntersecting 属性判断是否在视口中
        if(change.isIntersecting){
            const imgElement = change.target;
            imgElement.src = imgElement.getAttribute("data-src");
            observer.unObserve(imgElement);
        }
    }
})

observer.observe(img);

2. getBoundingClientReact

function lazyLoad(){
    for(let i = 0; i < num; i++){
        if(img[i].getBoundingClientRect().top < document.documentElement.clientHeight){
            if(img[i].getBoundingClientRect().top < document.documentElement.clientHeight) {
                if(img[i].getAttribute("src") !== "default.jpg"){
                    continue;
                }
                img[i].src = img[i].getAttribute("data-src");
            }
        }
    }
}

3. clientHeight、scrollTop 和 offsetTop

通过监听 scroll 事件来判断图片是否到达视口

let imgs = document.getElementsByTagName("img");

// 首次加载
lazyload();

window.addEventListener('scroll', lazyload);

function lazyload() {
    // 视口高度
    let viewHeight = document.documentElement.clientHeight;
    // 滚动条卷去的高度
    let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
    for(let i = 0; i < imgs.length; i++) {
        if(img[i].offsetTop < scrollTop + viewHeight) {
            if(img[i].getAttribute("src") !== "default.jpg"){
                continue;
            }
            img[i].src = img[i].getAttribute("data-src");
        }
    }
}