懒加载和预加载
懒加载
懒加载就是视图窗口到该位置的时候再加载图片,以防请求过多阻塞js加载(并发请求数量有限制),也可以减少对服务器的负担。特别像是素材库,图片相册之类,其实不需要加载全部的,可以使用分页加载和懒加载结合的方式。
懒加载的实现就是图片标签的src置为空或者是占位的loading图片,把它的真实地址记录起来,当图片的位置在视窗内,就把图片的src赋为真实的地址,浏览器就会去加载图片。
懒加载判断图片位置是否在视窗内有两种方式:
监听窗口的scroll事件,获取图片的位置
const images = document.querySelectorAll('.lazy-image');
images.forEach((image) => {
if (!image.dataset.src) {return;}
const bound = image.getBoundingClientRect();
if (bound.top < document.documentElement.clientHeight) {
image.src = image.dataset.src;
image.removeAttribute('data-src');
}
});
主要就是利用getBoundingClientRect计算它的位置,贴一张MDN的图。获得的是一个距离四个方向的差值,只要获取到top和clientHeight做对比就可以直到是不是在视窗内了。
同时对scroll事件的监听也可以增加节流以防止阻塞。
使用IntersectionObserver
IntersectionObserver可以理解为,为相应的元素增加一个观察者,一旦该元素和其他有重叠,就出发相应的事件。
它主要为以下几种情况诞生:
- 上文提到的懒加载
- 支持‘无线滚动’的网页,这样用户就不用不停的翻页了
- 可以知道广告是否被查看到了
- 只有当用户加载到的时候才做一些任务和复杂的渲染
相比于前一种方法,这种方法可以获得更好的性能表现,因为前一种方法所有的代码都是在主线程运行的,可能会阻碍一些交互操作。
而IntersectionObserver允许注册一个回调函数,只有当满足这个条件的时候才去调用回调函数,这样的话就不会阻塞主线程。
这篇文章就不赘述IntersectionObserver的具体使用了。但是它也是在比较新的浏览器上才支持,所以可以用两种方法结合的方法去实现懒加载。
const images = document.querySelectorAll('.lazy-image');
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
//is visible
const image = entry.target;
image.src = image.dataset.src;
observer.unobserve(image);
}
})
});
images.forEach((image) => {
observer.observe(image);
});
这样自主的去绑定和解绑观察期之后,如果图片全部加载完,就不需要再做多余的操作了。而第一种方法,需要自己查看需要加载的图片是否加载完毕,删减数组,并且解除scroll的绑定。