
本文共 4267 字,大约阅读时间需要 14 分钟。
一、懒加载的理解
-
懒加载:
1)懒加载其实就是延迟加载,是一种对网页性能优化的方式,比如当访问一个页面的时候,优先显示可视区域的图片而不一次性加载所有图片,当需要显示的时候再发送图片请求,避免打开网页时加载过多资源
2)在图片非常多的应用场景,为了提高页面加载速度,改善用户体验,我们对未出现在视野范围内的图片先不进行加载,等到出现在视野范围才去加载
3)懒加载(LazyLoad)是前端优化的一种有效方式,极大的提升用户体验 -
懒加载的运用场景:
1)当页面中需要一次性载入很多图片的时候,往往都是需要用懒加载的
2)如果一次ajax请求数量过多的图片,把它们全部加载出来,会显示的很慢,对于用户的显示体验造成很大的影响 -
懒加载的原理:
先把img的src指向空或者一个小图片,图片真实的地址存储在img一个自定义的属性里,< img src=”” data-src=”http://real.com/real.jpg” />
,等到此图片出现在视野范围内了,获取img元素,把data-src里的值赋给src -
判断元素是否在可视区域
1)通过document.documentElement.clientHeight
获取屏幕可视窗口高度
通过element.offsetTop
获取元素相对于文档顶部的距离
通过document.documentElement.scrollTop
获取浏览器窗口顶部与文档顶部之间的距离,也就是滚动条滚动的距离
判断element.offsetTop - document.documentElement.scrollTop < document.documentElement.clientHeight
是否成立,如果成立,元素就在可视区域内
2)通过getBoundingClientRect()方法来获取元素的大小以及位置,这个方法返回一个名为ClientRect的DOMRect对象,包含了top、right、botton、left、width、height这些值
当bound.top<=clientHeight
的时候,图片是在可视区域的
封装代码如下:
function isInSight(el) { const bound = el.getBoundingClientRect(); const clientHeight = window.innerHeight; //如果只考虑向下滚动加载 //const clientWidth = window.innerWeight; return bound.top <= clientHeight + 100;}
3)IntersectionObserver可以自动观察元素是否在视口内
可以用到intersectionRatio来判断是否在可视区域内,当intersectionRatio > 0 && intersectionRatio <= 1
即在可视区域内
封装代码如下:
var io = new IntersectionObserver(callback, option);// 开始观察io.observe(document.getElementById('example'));// 停止观察io.unobserve(element);// 关闭观察器io.disconnect();
- 加载图片
1)页面打开时需要对所有图片进行检查,是否在可视区域内,如果是就加载
2)封装代码如下:
function checkImgs() { const imgs = document.querySelectorAll('.my-photo'); Array.from(imgs).forEach(el => { if (isInSight(el)) { loadImg(el); } })}function loadImg(el) { if (!el.src) { const source = el.dataset.src; el.src = source; }
说明:优化的地方是设一个标识符标识已经加载图片的index,当滚动条滚动时就不需要遍历所有的图片,只需要遍历未加载的图片即可
- 函数节流优化
1)在类似于滚动条滚动等频繁的DOM操作时,可以进行函数节流和函数去抖
2)函数节流:让一个函数不要执行的太频繁,减少一些过快的调用来节流
3)基本步骤:
获取第一次触发事件的时间戳
获取第二次触发事件的时间戳
时间差如果大于某个阈值就执行事件,然后重置第一个时间
4)封装代码如下:
function throttle(fn, mustRun = 500) { const timer = null; let previous = null; return function() { const now = new Date(); const context = this; const args = arguments; if (!previous){ previous = now; } const remaining = now - previous; if (mustRun && remaining >= mustRun) { fn.apply(context, args); previous = now; } }}
说明:mustRun就是调用函数的时间间隔,无论多么频繁的调用fn,只有remaining>=mustRun时fn才能被执行
二、懒加载的实现
- 简单的懒加载实现
1)html 部分:
<!--data-* 全局属性:构成一类名称为自定义数据属性的属性,可以通过HTMLElement.dataset来访问--><img src="" data-src="./images/1.jpg" ><img src="" data-src="./images/2.jpg" ><img src="" data-src="./images/3.jpg" ><img src="" data-src="./images/4.jpg" ><img src="" data-src="./images/5.jpg" ><img src="" data-src="./images/6.jpg" ><img src="" data-src="./images/7.jpg" ><img src="" data-src="./images/8.jpg" >
2)js部分:
window.onload = function(){ // 获取元素 var img = document.querySelectorAll("img"); var len = img.length; // 存储图片的加载位置 var n = 0; // 获取图片的可视区域 var height = document.documentElement.clientHeight; var top = document.body.scrollTop || document.documentElement.scrollTop; for(var i=n;i<len;i++){ if(img[i].offsetTop< height + top){ if(img[i].getAttribute("src")==""){ img[i].src = img[i].getAttribute("data-src"); } n = i + 1; console.log("第"+n+"张图片"+",n="+n); } } };
3)在当打开页面的时候
console 控制台输出:
network 网络输出:
4)在打开页面滚动的时候
console 控制台输出:
network 网络输出:
5)通过在打开页面的时候,网页中的图片是没有全部加载出来的,从network中可以看出只加载出了两张图片资源。在打开页面进行滚动以后,后面的图片资源才慢慢加载出来,在network中看出,但是也只是展示出了五张图片的资源,展示出了我们的可视区域,剩下的图片也是没有加载出来,这样恰恰就可以实现了图片的懒加载,保证一次请求不会请求所有的资源,在出现可视区域后才会加载出来,提高了前端的性能优化
- 懒加载的封装函数
1)代码如下:
function checkImgs() { const imgs = Array.from(document.querySelectorAll(".my-photo")); imgs.forEach(item => io.observe(item));}function loadImg(el) { if (!el.src) { const source = el.dataset.src; el.src = source; }}const io = new IntersectionObserver(ioes => { ioes.forEach(ioe => { const el = ioe.target; const intersectionRatio = ioe.intersectionRatio; if (intersectionRatio > 0 && intersectionRatio <= 1) { loadImg(el); } el.onload = el.onerror = () => io.unobserve(el); });});
发表评论
最新留言
关于作者
