前言
在我学习前端性能优化过程中,了解到浏览器启动时会做的一些工作,由于浏览器是多线程运行,可以同时渲染很多张图片,那么问题来了,前端页面加载少量图片的时候很流畅,看不出卡顿,那么在大项目中一个页面渲染几百几千张图呢?是不是它们一下加载的话就会出现卡顿呢?这可会大大影响用户的体验啊。所有我们就学习一种图片加载性能的优化方式那就是----图片懒加载。
图片懒加载
它是一种常见的前端优化技术,主要用于改善网页性能和提升用户体验。在页面初始化时,只加载可视区域内的图片,当用户滚动页面,将要进入可视区域的图片才开始加载,这就是图片懒加载。
实现图片懒加载的方法有多种:
- 使用JavaScript或jQuery:通过监听滚动事件,判断图片是否进入可视区域,然后动态地为图片添加src属性。
- 使用Intersection Observer API:这是一种现代浏览器支持的API,可以更高效地检测元素是否进入视口,从而触发图片加载。
- *使用CSS和data-属性:在图片标签中使用data-src属性存储图片的真实路径,然后通过JavaScript在适当的时机替换为src属性。
- 使用第三方库:例如lozad.js、lazyload.js等,这些库提供了现成的解决方案,可以方便地实现图片懒加载。
图片懒加载的优点是减少初始页面加载时间,节省带宽,提高用户体验。缺点是需要额外的JavaScript代码,对于SEO可能有轻微影响(搜索引擎爬虫可能无法执行JavaScript,导致图片无法被正确识别)。
这里我们用第一个方法,使用JavaScript进行事件监听(主要是其它方法还不会哈哈哈)。
具体实现步骤
- 首先我们准备十几张图片:
- 给每一张图片的
src设置为空,而data-src是一个自定义数据属性,属于 HTML5 数据属性的一部分,其前缀data-表明这是一个用于存储私有自定义数据的属性。 - 在图片懒加载的场景下,
<img>标签的src属性可能会被设置为一个占位符图片的 URL 或者留空,而实际的图片 URL 则存储在data-src属性中。
实现步骤主要需理解img标签的src属性如果存了图片的url地址,浏览器加载页面时图片就会立马下载,所有才用data-src属性先存入src属性。
然后在JavaScript内拿到基本数据:
- 再设计一个事件监听,
DOMContentLoaded是一个在文档解析完成后的事件,但不包括样式表、图片和iframe的完成加载。这是JavaScript中的一个非常重要的事件,因为它标志着DOM树已经构建完成,此时可以通过JavaScript访问和操作DOM元素。
这个可以作为页面的第一次加载图片,后面可以触发其他事件来进行页面图片加载。
-
这样我们就可在加载函数内进行图片的懒加载了实现了:我们现在来分析一下,当进入页面时,我们需要加载当前显示屏显示的图片以及浏览过的图片,下面未浏览的图片暂时不显示。
-
也就是说,当前图片距离页面顶部的距离 应该小于 滑屏滚动的距离加上显示器的长度。 可加载的图片的条件判断如下:
imgs[i].offsetTop < screenHeight + scrollTop
- 循环每一张图片,如果满足判断条件,则将
data-src的url地址赋值给img标签的src属性。
imgs[i] 获取到了数组中第i个 <img> 元素,.dataset.src 则获取了该元素的 data-src 属性的值。
设置这段代码的意思是 当所有的图片都加载完成后,这个函数将不再被调用,其监听事件将被移除。监听的scroll事件是鼠标滚轮事件,因为我们每次滚动滑轮都会触发函数,让其重新计。
n = i + 1;
if(n === num){
console.log('所有图片均以加载完毕')
window.removeEventListener('scroll',throttleLayLoad)
}
然后完成加载后,调用如下函数:
_.throttle 函数是来自 Lodash 库的一个实用工具函数,用于限制函数的执行频率,即确保函数在指定的时间间隔内最多只能执行一次。这对于处理高频率触发的事件,比如窗口的滚动事件、调整大小事件等,特别有用,可以防止函数过于频繁地执行,从而优化性能。
最终效果如下:
刚开始页面只加载3张图:
当我们的不断的往下划时,图片会继续的加载。
这里对比一下不加_.throttle 函数的执行次数:
有_.throttle 函数:该函数会限制重载函数的执行,避免没必要的计算,以及无意义的函数执行。
没有_.throttle 函数:鼠标滑轮一动,它的函数就会执行多次。
最终的完整代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
*{
margin: 0;
padding: 0;
}
body{
background-color: gray;
}
img{
display: block;
margin-bottom: 50px;
width: 400px;
height: 400px;
}
</style>
</head>
<body>
<img data-price="20" data-src="https://img.36krcdn.com/20190808/v2_1565254363234_img_jpg">
<img data-src="https://img.36krcdn.com/20190905/v2_1567641293753_img_png">
<img data-src="https://img.36krcdn.com/20190905/v2_1567640518658_img_png">
<img data-src="https://img.36krcdn.com/20190905/v2_1567642423719_img_000">
<img data-src="https://img.36krcdn.com/20190905/v2_1567642425030_img_000">
<img data-src="https://img.36krcdn.com/20190905/v2_1567642425101_img_000">
<img data-src="https://img.36krcdn.com/20190905/v2_1567642425061_img_000">
<img data-src="https://img.36krcdn.com/20190904/v2_1567591358070_img_jpg">
<img data-src="https://img.36krcdn.com/20190905/v2_1567641974410_img_000">
<img data-src="https://img.36krcdn.com/20190905/v2_1567641974454_img_000">
<script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
<script>
const imgs = document.getElementsByTagName('img');
const num = imgs.length;
let n = 0;
document.addEventListener('DOMContentLoaded',()=>{
loadImage()
})
function loadImage(){
console.log('haha')
// 是否在可视区?
let screenHeight = document.documentElement.clientHeight;// 一整个屏幕的高度 宽度
let scrollTop = document.documentElement.scrollTop || document.body.scrollTop; // 滚动条上的偏移量(滚动的距离) 不同浏览器兼容问题
for(let i = 0; i < num; i++){
// console.log(imgs[i].offsetTop);
if(imgs[i].offsetTop < screenHeight + scrollTop){
// console.log(imgs[i].dataset.src);
imgs[i].src = imgs[i].dataset.src; //或者imgs[i].getAttribute('data-src')
n = i + 1;
if(n === num){
console.log('所有图片均以加载完毕')
window.removeEventListener('scroll',throttleLayLoad)
}
}
}
}
const throttleLayLoad = _.throttle(loadImage,500);
window.addEventListener('scroll',throttleLayLoad);
</script>
</body>
</html>
总结
图片懒加载技术显著优化了网页性能和用户体验,通过延迟非可视区域图片的加载,它有效加快了页面初次加载速度,节约了带宽和数据流量,同时也减轻了服务器负担。这一做法确保了用户能快速的看到页面主要内容,避免了渲染阻塞,优化了资源使用,特别是在长页面中避免加载未被浏览的图片。