图片懒加载
概述
图片懒加载是一种优化网页加载速度的技术,通过在网页中未在视口内的图片延迟加载,直到接近出现在视口即用户需要时才加载,从而提高网页的加载速度,增强用户体验感.
前置内容
浏览器加载机制
img 标签的资源加载由浏览器的渲染引擎处理,在加载页面时会对 img 标签中的资源开辟多个线程下载,尽管浏览器是多线程的,但当同时遇到很多资源时,浏览器的能力也是有限的。
思考如何解决这种问题
既然如此,浏览器遇到 img 标签, 就会下载 src 中的资源,何不妨只需要在用户需要的时候,才去进行下载呢?
解决方案
原生 img 标签 loading 属性
HTMLImageElement 的 loading 属性为一个字符串,它的值会提示用户代理告诉浏览器不在可视视口内的图片该如何加载。MDN
Demo 演示
<div></div>
<div></div>
<div></div>
<div></div>
<img src="https://picsum.photos/200/300" loading="lazy" />
div {
width: 200px;
height: 2000px;
background-color: aqua;
}
关于兼容性,很遗憾不支持 IE 浏览器.
通过 JS 检测图片是否出现在视口内
判断图片顶部到文档顶部的距离 是否小于 ‘浏览器可视窗口高度 + 滚动条滚过的高度‘
index.html
<div></div>
<img src="" data-src="https://picsum.photos/200/300" alt="懒加载图片" />
index.css
div {
height: 1000px;
background-color: pink;
}
index.js
document.addEventListener('scroll', () => {
const img = document.querySelector('img')
const imgOffsetTop = img.offsetTop // 图片顶部到文档顶部的距离
const windowHeight = window.innerHeight // 浏览器可视窗口高度
const scrollTop = window.scrollY || document.documentElement.scrollTop // 滚动条滚动的高度
// 判断条件
if (imgOffsetTop < windowHeight + scrollTop) {
console.log('图片已进入可视区域')
img.src = img.dataset.src // 设置图片的真实 src,触发加载
} else {
console.log('图片未进入可视区域')
}
})
IntersectionObserver API
核心是通过创建一个 IntersectionObserver 对象来观察目标元素是否进入可视区域(enties.isIntersecting 为布尔值,表示元素边界与视口边界是否有交集,entry.intersectionRatio 表示交界比例,返回值在 0 到 1 之间,未进入视口则为 0)
const intersectionObserver = new IntersectionObserver((enties) => {
if (enties[0].isIntersecting) {
//进入视口内
img.src = img.dataset.src
}
})
const img = document.querySelector('img')
intersectionObserver.observe(img)
Element.getBoundingClientRect() 方法
Element.getBoundingClientRect().top 是基于视口的左上角进行计算的, 因此只要图片顶部到视口顶部的距离小于视口高度,就认为图片出现在视口内,即 Element.getBoundingClientRect().top < window.innerHeight
const img = document.querySelector('img')
window.addEventListener('scroll', function () {
const rect = img.getBoundingClientRect()
console.log(rect.top)
if (rect.top < window.innerHeight) {
console.log('图片进入视口')
img.src = img.dataset.src
}
})