图片懒加载与预加载

  1. 图片懒加载

在网页中,滑动页面,直到能看到图片时,再加载图片。

前置准备

offsetTop:返回元素相对带有定位父元素上方的偏移;

clientHeight:元素内部的高度(以像素为单位),包含内边距,但不包括边框、外边距和水平滚动条(如果存在)。在根元素(<html> 元素)或怪异模式下的 <body> 元素上使用 clientHeight 时,该属性将返回视口高度(不包含任何滚动条);

scrollTop:属性可以获取或设置一个元素的内容垂直滚动的像素数。

图示:

实现懒加载

假设上图中某元素就是还未显示到的图片,当移动鼠标滚轮时,导致某元素上移,某元素即出现在了浏览器可视区域。此时有,某元素.offsetTop < clientHeight + scrollTop。这个条件即为判定图片是否出现在了浏览器可视区域。

function lazyload() {
    let imgs = document.querySelectorAll('img');
    for (let i = 0; i < imgs.length; i++) {
        if (imgs[i].offsetTop < document.documentElement.clientHeight + document.documentElement.scrollTop) {
            imgs[i].src = imgs[i].getAttribute('data-src');
        }
    }
}
//第一次进入页面,屏幕内的图片正常加载
window.onload = lazyload;
//监听滚动事件
window.addEventListener('scroll', lazyload);

此外,<img>会通过src属性的url来加载图片,因此将需要懒加载的图片url放到data-src属性中,这样src为空就不会加载图片了,或者也可以在src属性存放loading图片。当图片到达可视区时,再给<img>添加src属性。

优化

由于监听鼠标滚轮的滚动会非常频繁,因此要进行节流处理。

附完整代码:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>图片懒加载</title>
    <style>
        body {
            background-color: rgb(241, 222, 167);
        }

        div img {
            width: 220px;
            height: 375px;
            display: block;
            margin: 20px auto;
            border: 2px solid rgb(229, 174, 22);
            background-color: rgb(243, 243, 243);
        }
    </style>
</head>

<body>
    <div>
        <img data-src="https://www.z4a.net/images/2023/02/19/QQ20210227144725.md.jpg">
        <img data-src="https://www.z4a.net/images/2023/02/19/QQ20210227012315.md.jpg">
        <img data-src="https://www.z4a.net/images/2023/02/19/QQ20210227031103.md.jpg">
        <img data-src="https://www.z4a.net/images/2023/02/19/QQ20210227012319.md.jpg">
        <img data-src="https://www.z4a.net/images/2023/02/19/QQ20210227012327.md.jpg">
        <img data-src="https://www.z4a.net/images/2023/02/19/QQ20210227031058.md.jpg">
        <img data-src="https://www.z4a.net/images/2023/02/19/QQ20210227012249.md.jpg">
        <img data-src="https://www.z4a.net/images/2023/02/19/QQ20210227012334.md.jpg">
    </div>
</body>
<script>
    function lazyload() {
        let imgs = document.querySelectorAll('img');
        for (let i = 0; i < imgs.length; i++) {
            if (imgs[i].offsetTop < document.documentElement.clientHeight + document.documentElement.scrollTop) {
                imgs[i].src = imgs[i].getAttribute('data-src');
            }
        }
    }
    //第一次进入页面,屏幕内的图片正常加载
    window.onload = lazyload;
    //节流函数
    function throttle(fn, delay) {
        let preTime = Date.now();
        return function () {
            let context = this,
                args = arguments,
                nowTime = Date.now();
            // 如果两次时间间隔超过了指定时间,则执行函数。
            if (nowTime - preTime >= delay) {
                preTime = Date.now();
                return fn.apply(context, args);
            }
        };
    }
    //监听滚动事件
    window.addEventListener('scroll', throttle(lazyload, 500));
</script>

</html>

其它方法:

1 getBoundingClientRect + clientHeight

getBoundingClientRect:会返回一个对象,包含当前元素的大小及其相对于视口的位置。

如图,如果某元素.getBoundingClientRect().top < clientHeight就会出现在浏览器可视区域。

function lazyload() {
    let imgs = document.querySelectorAll('img');
    for (let i = 0; i < imgs.length; i++) {
        if (imgs[i].getBoundingClientRect().top < document.documentElement.clientHeight) {
            imgs[i].src = imgs[i].getAttribute('data-src');
        }
    }
}
//第一次进入页面,屏幕内的图片正常加载
window.onload = lazyload;
//监听滚动事件
window.addEventListener('scroll', lazyload);

2 Intersection Observer (推荐)

Intersection Observer(交叉观察器) :一种异步查询元素相对于其他元素或窗口位置的能力。常用于追踪一个元素在窗口的可视问题。

可见本质:目标元素与视口产生的交叉区,所以叫交叉观察器。

使用:

const i = new IntersectionObserver(callback, options);
//callback是可见性变化时的回调函数,options是配置对象(该参数可选)
//callback也有参数,entries是一个数组,每个元素都是IntersectionObserver的实例。描述了目标元素与root的交叉状态。如果有三个被观察的对象的可见性发生变化,entries数组就会有三个元素。
const i2 = new IntersectionObserver(
  entries => {
    console.log(entries);
  },options);

entries数组中的对象有如下属性、方法

属性

功能

boundingClientRect

返回包含目标元素的边界信息,返回结果与element.getBoundingClientRect() 相同

intersectionRatio

返回目标元素出现在可视区的比例

intersectionRect

用来描述root和目标元素的相交区域

isIntersecting

返回一个布尔值,下列两种操作均会触发callback:1. 如果目标元素出现在root可视区,返回true。2. 如果从root可视区消失,返回false

rootBounds

用来描述交叉区域观察者(intersection observer)中的根.

target

目标元素:与根出现相交区域改变的元素 (Element)

time

返回一个记录从 IntersectionObserver 的时间原点到交叉被触发的时间的时间戳

function Observer() {
    let imgs = document.querySelectorAll('img');
    let observer = new IntersectionObserver(entries => {
        entries.forEach(entry => {
            //判断目标元素是否出现在root可视区
            if (entry.isIntersecting) {
                entry.target.src = entry.target.dataset.src;
                //当图片出现在可视区,就停止监听
                observer.unobserve(entry.target);
            }
        })
    });
    //监听图片元素
    imgs.forEach(img => observer.observe(img));
}
Observer();

相较于offsetTop getBoundingClientRect两种方法,使用交叉观察器性能更优。

  1. 图片预加载

提前加载好后面会用到的图片

通过css实现

利用 background-image 属性,当打开非正式页面时,可以提前利用css请求所需要的图片资源,然后浏览器会将返回的图片资源进行本地存储。当需要在正式页面引入预加载图片时,可直接从本地中拿去,减少了正式页面等待请求时间。

缺点:会导致非正式页面css加载时间过长,可能导致非正式页面短暂空白。

css
#preload1 {
    background-image: url(https://www.z4a.net/images/2023/02/19/QQ20210227144725.md.jpg);
    width: 0;
    height: 0;
}

#preload2 {
    background-image: url(https://www.z4a.net/images/2023/02/19/QQ20210227012315.md.jpg);
    width: 0;
    height: 0;
}

#preload3 {
    background-image: url(https://www.z4a.net/images/2023/02/19/QQ20210227031103.md.jpg);
    width: 0;
    height: 0;
}
html
<img id="preload1">
<img id="preload2">
<img id="preload3">

通过js实现

使用 js 中的 image 对象,通过为 image 对象来设置 src 属性,来实现图片的预加载。

const imgs = [];
function preload() {
    for (let i = 0; i < arguments.length; i++) {
        imgs[i] = new Image();
        imgs[i].src = arguments[i];
    }
}
preload(
    'https://www.z4a.net/images/2023/02/19/QQ20210227144725.md.jpg',
    'https://www.z4a.net/images/2023/02/19/QQ20210227012315.md.jpg',
    'https://www.z4a.net/images/2023/02/19/QQ20210227031103.md.jpg'
);
  1. 懒加载与预加载区别

懒加载也叫延迟加载,指的是在长网页中延迟加载图片的时机,当用户需要访问时,再去加载,这样可以提高网站的首屏加载速度,提升用户的体验,并且可以减少服务器的压力。它适用于图片很多,页面很长的电商网站的场景。

预加载指的是将所需的资源提前请求加载到本地,这样后面在需要用到时就直接从缓存取资源。通过预加载能够减少用户的等待时间,提高用户的体验。常见于漫画、图片画廊场景。

这两种方式都是提高网页性能的方式,两者主要区别是一个是提前加载,一个是迟缓甚至不加载。懒加载对服务器前端有一定的缓解压力作用,预加载则会增加服务器前端压力。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值