懒加载和预加载的目标都是为了进步用户的体验,二者行为是相同的,一个是提早加载,另一个是提前加载。懒加载对缓解服务器压力有肯定作用,预加载则会增长服务器前端压力缓存。
懒加载 lazyload
懒加载:又叫提早加载、按需加载,当咱们关上一个网页,优先展现的首屏图片就先加载,而其余的图片,等到须要去展现的时候再去申请图片资源。
目标:更好的加载页面的首屏内容,对于含有不少图片的比拟长的网页来讲,可能加载的更快,防止了首次关上时,一次性加载过多图片资源,是对网页性能的一种优化形式。
原理:浏览器解析到img标签的src有值,才会去发动申请,那么就能够让图片须要展现时,才对其src赋值真正的图片地址。
实现代码
<!DOCTYPE html><html lang="en"> <head> <meta charset=UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>图片懒加载</title> <style> * { margin: 0; padding: 0; } img { margin: 50px; width: 400px; height: 200px; } </style> </head> <body> <div class="img-container"> <img src="loading.gif" alt="" data-src="1.jpg" class="lazyload" /> </div> <div class="img-container"> <img src="loading.gif" alt="" data-src="2.jpg" class="lazyload" /> </div> <div class="img-container"> <img src="loading.gif" alt="" data-src="3.jpg" class="lazyload" /> </div> <div class="img-container"> <img src="loading.gif" alt="" data-src="4.jpg" class="lazyload" /> </div> <div class="img-container"> <img src="loading.gif" alt="" data-src="5.jpg" class="lazyload" /> </div> <script> const imgs = [...document.querySelectorAll(".lazyload")]; //img元素转换成数组 lazyload(); //初始调用一次 window.addEventListener("scroll", lazyload, false); //监听滚动时也调用lazyload函数,冒泡阶段 //懒加载 function lazyload() { for (let i = 0; i < imgs.length; i++) { const $img = imgs[i]; //每次循环拿到每一个img元素 if (isInVisibleArea($img)) { //判断img元素是否在可视区域内 $img.src = $img.dataset.src; //用data-src替换src属性 imgs.splice(i, 1); //对应该索引的元素删掉 i--; } } } // 判断DOM元素是否在可视区域内,返回true/false function isInVisibleArea($el) { const rect = $el.getBoundingClientRect(); console.log(rect); return rect.bottom > 0 && rect.top < window.innerHeight && rect.right > 0 && rect.left < window.innerWidth; } </script> </body></html>
实现细节
1 如何加载图片
用img的data-src属性寄存真正须要显示的图片的门路,当页面滚动直到图片呈现在可视区域时,将data-src中的图片地址值赋值给src属性值。
2 如何判断一个元素呈现在可视区域
监听滚动事件,用getBoundingClientRect()
获取DOM元素在页面的地位,该函数返回rect对象,如下图所示,如果rect.bottom
为正数,rect.top
大于页面高度,或者rect.right
为正数,或者rect.left
大于页面宽度,则认为元素已不在页面的可视区域。
const rect = element.getBoundingClientRect();
- rect.top:元素上边到视窗上边的间隔;
- rect.bottom:元素下边到视窗上边的间隔;
- rect.left:元素右边到视窗右边的间隔;
- rect.right:元素左边到视窗右边的间隔;
- window.innerHeight:视窗高度
- window.innerWidth: 视窗宽度
实现成果
参考视频解说:进入学习
利用开发者工具咱们能够看到如下截图:
- 最后关上页面:只显示前两张图片,前面三张图片还没有呈现在以后页面
因为前面三张还没有呈现,那么就放弃loading.gif,这样就节俭了加载的工夫,当咱们持续滚动直到呈现页面底部,通过开发者工具看到如下的截图:
预加载 preload
预加载:提前加载所须要的图片资源,加载结束后会缓存到本地,当须要时能够立即显示进去。
目标:看完一张图片,再看下一张时,会有一段空白的加载工夫,如果网络不是很好,加载的工夫就会比拟久,预加载能够让用户无需期待,取得间接预览的良好体验。
利用场景:看漫画时,如果咱们看完 2 了 ,想看 3 ,3 却还没加载完就会大大降低体验感,而如果能在咱们预览 2 这段时间里就提前加载好 3 , 等到咱们看 3 时就间接外面显示。那么就体验会好很多。
实现办法
1 通过CSS
步骤
- 创立用来预加载的标签
- 给标签应用背景图,背景图的门路是须要预加载的图片资源,并将图片移到看不见的中央,或放大到看不见。
- 当应用到曾经预加载好的图片时,会间接应用缓存好的图片资源,而不须要向服务器发送申请。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>CSS 预加载</title> <style> ul,li{ padding:0; margin:0; list-style:none; } img { width: 300px; } #preImg1 { background-image: url('1.jpg'); width: 0; height: 0; /* 暗藏用来预加载的标签 */ } #preImg2 { background-image: url('2.jpg'); width: 0; height: 0; } #preImg3 { background-image: url('3.jpg'); width: 0; height: 0; } </style></head><body> <button onclick="show()">点击显示图片</button> <ul> <li id="preImg1"/> <li id="preImg2"/> <li id="preImg3"/> </ul></body><script> const show = function () { document.querySelector("ul").innerHTML = ` <li><img src="1.jpg"></li> <li><img src="2.jpg"></li> <li><img src="3.jpg"></li>` }</script></html>
2 通过JavaScript
步骤
- 将须要预加载的图片资源的 URL 保留在数组里
- 循环遍历 URL 数组执行以下步骤,直到完结
- 创立一个 image 对象
new Image()
- 将 image 对象的 src 属性的值指定为预加载图片的 URL
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>图片预加载</title> <style> .img-container { display: flex; align-items: center; height: 100vh; background-color: rgba(0, 0, 0, 0.5); } img { width: 100%; } * { margin: 0; padding: 0; } </style> </head> <body> <div class="img-container"> <img src="1.jpg" alt="" id="img" /> </div> <script> const imgs = [ "2.jpg", "3.jpg", "4.jpg", "5.jpg", ]; let i = 0; const $img = document.getElementById("img"); // 页面一开始调用preload,加载数组的第一个元素 preload(imgs[i]) .then((data) => {}) .catch(() => {}); // 点击切换 $img.addEventListener( "click", () => { if (i < imgs.length) { $img.src = imgs[i]; // 将数组元素的src赋值给页面元素 i++; if (i < imgs.length) { preload(imgs[i]); // 当索引小于数组length,预加载下一个图片 } } else { console.log("曾经是最初一张了!"); // 当 索引和 数组length雷同 则数组内没元素了 } }, false ); // 预加载 function preload(src) { return new Promise((resolve, reject) => { const image = new Image(); // 创立一个新的图片标签 image.addEventListener("load", () => resolve(image), false); // 图片加载实现调用胜利状态 image.addEventListener("error", () => reject(), false); // 图片加载失败调用失败状态 image.src = src; // 将传进来的src赋值给新的图片 }); } </script> </body></html>
实现成果
总结比照
懒加载 | 预加载 | |
---|---|---|
定义 | 提早加载、按需加载 | 提前加载、不须要也提前加载 |
目标 | 更好更快地加载页面首屏内容,网页性能优化 | 让用户无需期待,取得间接预览的良好体验 |
毛病 | 须要监听图片是否显示,消耗浏览器性能 | 占用较多的后盾资源,可能一次性加载较多的图片 |
利用场景 | 电商搜寻产品时图片展现 | 观看漫画时,每次切换的下一张图片提前加载 |