本文已参与「新人创作礼」活动,一起开启掘金创作之路
图片资源体积影响加载请求,影响性能很严重
花最少的时间,最大的优化
兼容性还行,还简单
chrome 76以后出的
可以实现懒加载效果
"" lazy="loading" alt="">
图片懒加载的关键在于获取元素的位置,
并判断其是否出现在视口。故有以下三种方式
滚动监听+scrollTop+offsetTop+innerHeight
滚动监听+getBoundingClientRect()
intersectionObserve()
ntersection Observer API
可以异步监听目标元素与其祖先或视窗(viewport)交叉状态的手段。
意思就是浏览器可以观察元素是否在可视区内。
/*
初始化 Intersectionobserver 类
`callback`是当元素的可见性变化时候的回调函数,`options`是一些配置项
*/
const observer = new IntersectionObserver(callback, options);
/* 监听对应的 DOM 元素 */
observer.observe(DOM);
/* 取消对 DOM 元素的监听 */
observer.unobserve(DOM);
/*
root:用于观察的根元素,默认是浏览器的视口
rootMargin:用来缩放视窗的的大小,用法和 CSS 类似,
`10px 10px 30px 20px`表示top、right、bottom 和 left 扩大的对应值,
`10px 20px 5px`表示top,left&right, bottom 扩大的对应值
thresholds: 当被监听的元素与根元素的交叉比例达到该值时触发回调函数,
默认为`[0]`, `0.1`表示当交叉比例达到`0.1`时触发回调,
`[0,0.5]`表示当交叉比例达到`0`和`0.5`时都会触发回调
*/
const options = {
root: null,
rootMargin: 0,
thresholds: 1,
};
/*
回调函数在监听的 DOM 元素可见性变化时触发
entries 中有多个参数,我们使用到以下两个参数
isIntersecting 表示观察的元素是否出现在 root 元素可视区,
intersectionRatio 表示观察的元素出现在 root 元素的比例
*/
function callback(entries) {
entries.forEach(entry => {
if (entry?.isIntersecting || entry?.intersectionRatio > 0) {
// 在此处进行图片地址替换
}
});
}
当你的网站非常注重浏览器的兼容性时,以上的方法就无法满足你的需求,
我们需要使用scroll及其他事件处理程序配合getBoundingClientRect来实现代码降级,
从而确定确定元素是否位于视区中。此方法几乎可以兼容所以浏览器,
但是性能不如intersectionObserve和loading=lazy
// 用于存当前页面已有的图片
observerMap = new Map();
// 通过滚动事件触发 scrollHandle 回调
window.addEventListener('scroll', scrollHandle, true);
// 每次回调里进行遍历已有图片列表
function scrollHandle() {
for (let dom of observerlist) {
// 判断元素是否在可视区从而判断是否替换真实地址
}
}
// 判断元素是否在可视区
function checkDomInView(element) {
const viewwidth = window.innerWidth || document.documentElement.clientWidth;
const viewHeight = window.innerHeight || document.documentElement.clientHeight;
const { top, right, bottom, left } = element.getBoundingClientRect();
return left < viewwidth && right > 0 && top < viewHeight && bottom > 0;
}