博客之前集成了Douban数据的展示功能,不过由于数据一次性加载过多,且都是有图片的数,导致在进入该网页时会使浏览器卡死3-5秒,等到图片完全加载完毕后才能正常操作,非常影响用户体验。
我检查了一下,发现卡顿的原因主要还是一次性发起的图片加载请求太多了,查了下资料,似乎下一代的HTTP2.0协议好像对这方面做了优化。但是常规做法还是使用懒加载来处理,也就是滚到图片位置才进行图片请求。
不过我不太想使用第三方的库来处理这个问题,其他库用起来麻烦,而且很臃肿,我其实只要简单的实现这个功能就好了。之前在移植Smart主题的TOC功能到二〇一九上时发现他使用了 IntersectionObserver
这个函数来处理,便查了一下这个函数的介绍:
Intersection Observer API 提供了一种异步检测目标元素与祖先元素或 viewport 相交情况变化的方法。
这个函数多用于以下几种情况
后查了一些范例,便参照这个教程的实现了图片的懒加载功能
<div class="lazyload-wrapper ">
<img src="https://iph.href.lu/150x220?text=Loading&fg=666666&bg=cccccc" data-src="{%= o.douban[i].poster %}" referrer-policy="no-referrer" class="lazyload" alt="{%= o.douban[i].title %}" width="150" height="220">
</div>
let images = document.querySelectorAll(".lazyload");
let observer = new IntersectionObserver(entries => {
entries.forEach(item => {
if (item.isIntersecting) {
item.target.src = item.target.dataset.src; // 开始加载图片,把data-src的值放到src
observer.unobserve(item.target); // 停止监听已开始加载的图片
}
});
},
{
rootMargin: "0px 0px 500px 0px" // 交叉视图前的500像素时,就开始派发事件
}
);
images.forEach(item => observer.observe(item));
原理其实很简单
data-src
,添加 lazyload
类用于之后可以获取到图片。isIntersecting
(如果 isIntersecting
为真,则该图片至少已经达到我们设置的rootMargin值以内) 判断,如果进入了目标区间内则将img的data-src设置为src属性。unobserve
停止对这个片检测。我记得以前实现起来挺复杂的,现在有了个函数只需要简单的几行代码就可以实现,真的方便。
END
loading="lazy"
即可。通过性能检测工具可以发现 spacingNode
、 spacingNodeByXPath
阻塞了进程,不知道是什么原因。我尝试将调用函数换成 spacingPageBody()
后页面性能恢复正常。可能是body之外的某些标签阻塞了函数执行。