web前端图片加载的优化

图像延迟加载想要得到更好的性能体验 , 只靠资源压缩与恰当的文件格式选型 , 是很难满足期望的 。我们还需要针对资源加载过程进行优化 。
什么是延迟加载?下图是京东商城的手机端首页 , 当元素没有滑动到视线内时 , 图片src属性放置了一个很小的图片 , init_src属性放置了真正的图片 , 只要当该元素滑动到视线内部 , 才会将init_src属性赋值给src去加载真实的图片 , 这就是一个简单的图片延迟加载的过程 。

web前端图片加载的优化

文章插图
 

web前端图片加载的优化

文章插图
 
传统方式延迟加载就是事件监听的方式 , 通过监听scroll事件与resize事件 , 并在事件的回调函数中去判断 , 需要进行延迟加载的图片是否进入视窗区域 。
我们只需要关注三个属性 。
  • class属性 , 稍后会在JAVAScript中使用类选择器选取需要延迟加载处理的〈img〉标签 。
  • src属性 , 加载前的占位符图片 , 可用Base64图片或低分辨率的图片 。
  • data-src属性 , 通过该自定义属性保存图片真实的URL外链 。

web前端图片加载的优化

文章插图
 
加入页面中有多张这样的图片需要加载 。具体的JavaScript实现逻辑如下 , 在文档的DOMContentLoaded事件中 , 添加延迟加载处理逻辑 , 首先获取class属性名为lazy的所有〈img〉标签 , 将这些标签暂存在一个名为lazyImages的数组中 , 表示需要进行延迟加载但还未加载的图片集合 。当一个图片被加载后 , 便将其从lazyImages数组中移除 , 直到lazyImages数组为空时 , 表示所有待延迟加载的图片均已经加载完成 , 此时便可将页面滚动事件移除 。
这里使用了getBoundingClientRect()函数获取元素的相对位置.
rectObject = object.getBoundingClientRect();rectObject.top:元素上边到视窗上边的距离;
rectObject.right:元素右边到视窗左边的距离;
rectObject.bottom:元素下边到视窗上边的距离;
rectObject.left:元素左边到视窗左边的距离;
web前端图片加载的优化

文章插图
 
对于只可上下滚动的页面 , 判断一个图片元素是否出现在屏幕视窗中的方法其实显而易见 , 即当元素上边缘距屏幕视窗顶部的top值小于整个视窗的高度window.innerHeight时 , 预加载的事件处理代码如下:
document.addEventListener(DOMContentLoaded, function() {const imags = [].slice.call(document.querySelector('.lazy'))const active = false; // 限制函数被频繁调动function load() {if(active === false) {active = truesetTimeout(() => {imags.forEach((img) => {const objPos = img.getBoundingClientRect();if(objPos.top <= window.innerHeight && objPos.bottom >=0 && img.display !== 'done') {img.src = https://www.isolves.com/it/cxkf/bk/2021-09-06/img.dataset.src;img.classList.remove('lazy')imags.filter((i) => (i !== img))if(imags.length === 0) {document.removeEventListener('scroll', load)window.removeEventListener('resize', load)window.removeEventListener('orientationchange', load)}}})active = false}, 200)}}document.addEventListener('scroll', load)window.addEventListener('resize', load)window.addEventListener('orientationchange', load)})这种方式的有点就是兼容性比较好 , 缺点是频繁地进行计算必然会影响性能 , 代码也会比较繁琐 。
实现图片的延迟加载:Intersection Observer方式现代浏览器已大多支持了Intersection Observer API , 用一句话简述:每当因页面滚动或窗口尺寸发生变化 , 使得目标元素(target)与设备视窗或其他指定元素产生交集时 , 便会触发通过Intersection Observer API配置的回调函数 , 在该回调函数中进行延迟加载的逻辑处理 , 会比传统方式显得更加简洁而高效 。
简单来说 , 目标元素的可见性变化时 , 就会调用观察器的回调函数 callback 。
callback一般会触发两次 。一次是目标元素刚刚进入视口(开始可见) , 另一次是完全离开视口(开始不可见) 。
document.addEventListener(DOMContentLoaded, function() {const imags = [].slice.call(document.querySelector('.lazy'))if(window.IntersectionObserver && window.IntersectionObserverEntry && window.IntersectionObserverEntry.prototype.intersectionRatio) {var lazyImgObserver = new IntersectionObserver((entries, observer) => {entries.forEach((entry)=> {if(entry.isIntersecting) {var lazyImg = entry.target;lazyImg.src = https://www.isolves.com/it/cxkf/bk/2021-09-06/lazyImg.dataset.src;lazyImg.classList.remove('lazy');lazyImgObserver.unobserve(lazyImg)}})})imags.forEach((img) => {lazyImgObserver.observe(img)})}})


推荐阅读