Skip to content

图片懒加载(lazyload) #81

Open
@TieMuZhen

Description

@TieMuZhen

意义

对于图片过多的页面,为了加速页面加载速度,所以很多时候我们需要将页面内未出现在可视区域内的图片先不做加载, 等到滚动到可视区域后再去加载。

原理

将页面中的img标签src指向一张小图片或者src为空,然后定义data-src(这个属性可以自定义命名)属性指向真实的图片。src指向一张默认的图片,否则当src为空时也会向服务器发送一次请求。可以指向占位图片的地址。

<img src="default.jpg" data-src="./imgs/1.jpg" />

当载入页面时,先把可视区域内的img标签的data-src属性值赋给src,然后监听滚动事件,把用户即将看到的图片加载。这样便实现了懒加载。

代码实现

在懒加载实现过程中,有两个关键:当前可视区域的高度元素距离可视区域顶部的高度

当前可视区域的高度,在和现代浏览器及IE9以上的浏览器中,可以用window.innerHeight属性获取。在低版本IE中,用document.documentElement.clientHeight获取,这里我们兼容这两种情况:

const viewHeight = window.innerHeight || document.documentElement.clientHeight;

而元素距离可视化区域顶部的高度,我们使用getBoundingClientRect()方法来获取元素的大小及其相对于视口的位置。

该方法返回值是一个 DOMRect 对象,这个对象是由该元素的 getClientRects() 方法返回的一组矩形的集合,就是该元素的 CSS 边框大小。返回的结果是包含完整元素的最小矩形,并且拥有left, top, right, bottom, x, y, width, 和 height这几个以像素为单位的只读属性用于描述整个边框。除了width 和 height 以外的属性是相对于视图窗口的左上角来计算的。

其示意图如下,除了widthheight以外的属性是相对于视图窗口的左上角来计算的

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        img {
            display: block;
            margin-bottom: 50px;
            width: 400px;
            height: 400px;
        }
    </style>
</head>
<body>
    <img src="default.jpg" data-src="./imgs/1.jpg" alt="">
    <img src="default.jpg" data-src="./imgs/2.jpg" alt="">
    <img src="default.jpg" data-src="./imgs/3.jpg" alt="">
    <img src="default.jpg" data-src="./imgs/4.jpg" alt="">
    <img src="default.jpg" data-src="./imgs/5.jpg" alt="">
    <img src="default.jpg" data-src="./imgs/6.jpg" alt="">
</body>

JavaScript

// 获取所有图片的标签
const imgs = document.querySelectorAll("img");
// 获取可视区域的高度
const viewHeight = window.innerHeight || document.documentElement.clientHeight;
// num用于统计当前显示到了哪一张图片,避免每次都从第一张图片开始检查是否露出
let num = 0;
function lazyload(){
    for(let i = num; i < imgs.length; i++){
        // 用可视区域减去元素顶部距离可视区域顶部的高度
        let distance = viewHeight - imgs[i].getBoundingClientRect().top;
        // 如果可视区域高度大于等于元素顶部距离可视区域顶部的高度,说明元素露出
        if(distance >= 0){
            imgs[i].src = imgs[i].getAttribute('data-src');
            num = i + 1;
        }
    }
}
// 监听scroll事件
window.addEventListener('scroll', lazyload, false); // false:事件在冒泡阶段执行

参考文献

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions