什么是懒加载
懒加载其实就是延迟加载,是对网页性能优化的一种方式,比如当访问一个页面的时候,优先显示可视区域的图片而不是一次性加载所有的图片,当需要显示的时候在发送图片请求,避免打开网页的时候加载过多的资源。
什么时候使用懒加载
- 当页面中一次性载入很多图片的时候
- SPA页面中的图片一定要做懒加载,否则你会发现路由跳转很慢,很慢。因为新页面路由是在dom挂在完之后才会跳转的。如果你的页面有很多图片,那么一定要做图片懒加载,否则会瞬间发出很多请求,还涉及页面渲染,重绘。因为处理并发请求比较慢,浏览器对同一域名并发http请求是有限制的(chrome是6个,一般都在8个以内),但是加载到渲染还是很消耗性能。可以在dom mount之后,加个延时做图片懒加载。这样页面会跳转会快很多。
懒加载原理
标签有一个属性是src,用来表示图像的URL,当这个属性的值不为空时,浏览器就会根据这个值发送请求。如果没有src属性,就不会发送请求。
可以通过先不给 设置 src,把图片真正的 URL 放在另一个属性 data-src 中,在需要的时候也就是图片进入可视区域的之前,将 URL 取出放到 src 中。
实现
HTML结构
1 | <div class="container"> |
仔细观察一下, 标签此时是没有 src 属性的,只有 alt 和 data-src 属性。
alt 属性是一个必需的属性,它规定在图像无法显示时的替代文本。 data-* 全局属性:构成一类名称为自定义数据属性的属性,可以通过HTMLElement.dataset来访问。
如何判断元素是否在可视区域
通过scrollTop判断
- 通过
document.documentElement.clientHeight
获取屏幕可视窗口高度 - 通过
element.offsetTop
获取元素相对于文档顶部的距离 - 通过
document.documentElement.scrollTop
获取浏览器窗口顶部与文档顶部之间的距离,也就是滚动条滚动的距离
然后判断element.offsetTop - document.documentElement.scrollTop < document.documentElement.clientHeight
是否成立,如果成立,元素就在可视区域内。
使用getBoundingClientRect
通过getBoundingClientRect()
方法获取元素的大小及其相对于视口的位置,这个方法返回一个名为ClientRect
的DOMRect
对象,包含了top、right、bottom、left、width、height这些值
返回的元素位置是相对于左上角而言的,而不是边距。假设const bound = el.getBoundingClientRect();
来表示图片到可视区域顶部距离; 并设 const clientHeight = window.innerHeight;
来表示可视区域的高度。随着滚动条的向下滚动,bound.top
会越来越小,也就是图片到可视区域顶部的距离越来越小,当bound.top===clientHeight
时,图片的上沿应该是位于可视区域下沿的位置的临界点,再滚动一点点,图片就会进入可视区域。也就是说,在bound.top<=clientHeight
时,图片是在可视区域内的。
1 | function isInSight(el) { |
加载图片
页面打开时需要对所有图片进行检查,是否在可视区域内,如果是就加载。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16function checkImgs() {
const imgs = document.querySelectorAll(".my-photo");
Array.from(imgs).forEach(el => {
if (isInSight(el)) {
loadImg(el);
}
});
}
function loadImg(el) {
// 这里可以保存一个已加载过的图片,这样每次检查的时候就不用循环全部的图片了
if (!el.src) {
const source = el.dataset.src;
el.src = source;
}
}
上面的代码还有个问题就是 checkImgs 函数什么时候执行,这就要用来函数的防抖