使用原生的js实现简易的图片延时加载

什么是延时加载?

图片延迟加载也称 “懒加载”,通常应用于图片比较多的网页
为什么要使用延时加载?假如一个网页中,含有大量的图片,当用户访问网页时,那么浏览器会发送n个图片的请求,加载速度会变得缓慢,性能也会下降 。如果使用了延时加载,当用户访问页面的时候,只加载首屏中的图片;后续的图片只有在用户滚动时,即将要呈现给用户浏览时再按需加载,这样可以提高页面的加载速度,也提升了用户体验 。而且,统一时间内更少的请求也减轻了服务器中的负担 。
延时加载的原理基本原理就是最开始时,所有图片都先放一张占位图片(如灰色背景图),真实的图片地址则放在 data-src 中,这么一来,网页在打开时只会加载一张图片 。
然后,再给 window 或 body 或者是图片主体内容绑定一个滚动监听事件,当图片出现在可视区域内,即滚动距离 + 窗体可视距离 > 图片到容器顶部的距离时,将讲真实图片地址赋值给图片的 src,否则不加载 。
使用原生js实现图片的延时加载延时加载需要传入的参数:
var selector = options.selector || 'img', imgSrc = https://www.isolves.com/it/cxkf/yy/js/2019-09-19/options.src || 'data-src', defaultSrc = options.defaultSrc || '', wrApper = options.wrap || body;其中:
  • wrapper :延时加载的容器 。在该容器下,所有符合图片选择器条件的图片均会延时加载 。
  • selector :图片选择器 。表示需要延迟加载的图片的选择器,如 img.lazyload-image ,默认为所有的 img 标签 。
  • imgSrc :图片真实地址存放属性 。表示图片的真实路径存放在标签的哪个属性中,默认为 data-src 。
  • defaultSrc :初始加载的图片地址,默认为空,当为空时,不处理延时加载的图片的路径,若图片本身没有路径,则显示为空 。
  • 获取容器中所有的图片 。
function getAllImages(selector){ return Array.prototype.concat.apply([], wrapper.querySelectorAll(selector));}该函数在容器中查找出所有需要延时加载的图片,并将 NodeList 类型的对象转换为允许使用 map 函数的数组 。
如果设置了初始图片地址,则加载 。
function setDefault(){ images.map(function(img){ img.src = https://www.isolves.com/it/cxkf/yy/js/2019-09-19/defaultSrc; })}给 window 绑定滚动事件
function loadImage(){ var nowHeight = body.scrollTop || doc.documentElement.scrollTop; console.log(nowHeight); if (images.length > 0){ images.map(function(img, index) { if (nowHeight + winHeight > img.offsetTop) { img.src = https://www.isolves.com/it/cxkf/yy/js/2019-09-19/img.getAttribute(imgSrc); images.splice(index, 1); } }) }else{ window.onscroll = null; }}window.onscroll = loadImage();每次滚动网页时,都会遍历所有的图片,将图片的位置与当前滚动位置作对比,当符合加载条件时,将图片的真实地址赋值给图片,并将图片从集合中移除;当所有需要延时加载的图片都加载完毕后,将滚动事件取消绑定 。
测试是否可行
测试结果:
从chrome的网络请求图中可见,5张图片并不是在网页打开的时候就请求了,而是当滑动到某个区域时才触发加载,基本实现了图片的延时加载 。
测试结果
性能调整
上述只是简单的实现了一个延时加载的 demo,还有很多地方需要调整和完善 。
调整 1:onscroll 函数可能会被覆盖
问题:
因为有时候页面需要滚动无限加载时,插件会重写 window 的 onscroll 函数,从而导致图片的延时加载滚动监听失效 。
解决办法:
需要更改为将监听事件注册到 window 上,移除时只需要移除相应的事件即可 。
调整后的代码
function bindListener(element, type, callback){ if (element.addEventListener) { element.addEventListener(type, callback); }else if (element.attachEvent) { //兼容至 IE8 element.attachEvent('on'+type, callback) }else{ element['on'+type] = callback; }}function removeListener(element, type, callback){ if (element.removeEventListener) { element.removeEventListener(type, callback); }else if (element.detachEvent) { element.detachEvent('on'+type, callback) }else{ element['on'+type] = callback; }}function loadImage(){ var nowHeight = body.scrollTop || doc.documentElement.scrollTop; console.log(nowHeight); if (images.length > 0){ images.map(function(img, index) { if (nowHeight + winHeight > img.offsetTop) { img.src = https://www.isolves.com/it/cxkf/yy/js/2019-09-19/img.getAttribute(imgSrc); images.splice(index, 1); } }) }else{ //解绑滚动事件 removeListener(window, 'scroll', loadImage) }}//绑定滚动事件bindListener(window, 'scroll', loadImage)


推荐阅读