前端代码实现 LazyLoad

代码笔记 | 📅 2020-10-12 | javascript

原理

首先,在图片未加载时,将 <img> 标签的 src 属性设置为空字符串,并将 src 的值保存下来。此举可以使得图片不被加载。

然后监听 onscroll 事件,在此事件触发时,检查所有 <img> 标签是否在可视范围内。对于在可视范围的 <img> 标签,把存储的 src 属性的值,赋值给 src 属性。此时,图片开始加载。

关键点

置空 src 属性的时机

由于浏览器会在解析到 <img> 标签后,立即开始加载图像,所以置空 src 的操作应越早越好。

我觉得应该放在 <body> 标签末尾,加载其他 js 脚本之前,这个位置比较合理。

另外,在 src 被置空后,已经开始加载的图像会立即终止,变为“挂起”状态。如果需处理的话,应另想办法。

存储 src 的位置

我是直接随便赋值给了 <img> 标签的其他属性里了。这样,就不用全局变量来存储,看起来比较清真。

代码实现

// 循环所有 <img> 标签
for (let i = 0; i < document.images.length; i++) {

    // 将 <img> 标签的 src 属性赋值给 srccache 属性
    document.images[i].srccache = document.images[i].src;

    // 将 <img> 标签的 src 属性置空
    document.images[i].src = "";

    // 添加 alt 属性,让 <img> 显示“等待加载”
    document.images[i].alt = "等待加载......";
}

// 向 `onscroll` 添加事件处理函数
window.onscroll = function(){
    
    // 获得可视区域的高度
    let viewHeight = document.documentElement.clientHeight || window.innerHeight;

    // 循环所有 <img> 标签
    for (let i = 0; i < document.images.length; i++) {

        // 若存储 src 的属性木有值,则跳过
        if (document.images[i].srccache == undefined || document.images[i].srccache == "") {
            continue;
        }

        // 获取 <img> 标签相对于视图区域的顶部位置
        let imgTop = document.images[i].getBoundingClientRect().top;

        // 若 <img> 标签的 src 属性为空,且在视图区域之内,则将 src 赋值回来
        if (document.images[i].src == document.URL && imgTop > 0 && imgTop < viewHeight) {

            // 将 srccache 属性存储的值赋值回 src 属性
            document.images[i].src = document.images[i].srccache;

            // 将 srccache 置空,表示此标签已经处理
            document.images[i].srccache = "";
        }

    }
};