定义:延迟加载也称为惰性加载,即在长网页中延迟加载图像。用户滚动到它们以前,视口外的图像不会加载。这与图像预加载相反,在长网页上使用延迟加载将使网页加载更快。在某些状况下,它还能够帮助减小服务器负载。html
举个例子来讲明,当打开淘宝首页的时候,只有在浏览器窗口里的图片才会被加载,当你滚动首页向下滑的时候,进入视口内的图片才会被加载,而其它从未进入视口的图像不会也不会加载。api
那么延迟加载有什么好处:数组
那么下面就介绍延迟加载的三种实现方式:浏览器
第一种:服务器
首先将页面上的图片的 src 属性设为 loading.gif,而图片的真实路径则设置在 data-src 属性中,页面滚动的时候计算图片的位置与滚动的位置,当图片出如今浏览器视口内时,将图片的 src 属性设置为 data-src 的值,这样,就能够实现延迟加载。闭包
下面是具体的实现代码:函数
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Lazyload 1</title> <style> img { display: block; margin-bottom: 50px; height: 200px; } </style> </head> <body> <img src="images/loading.gif" data-src="images/1.png"> <img src="images/loading.gif" data-src="images/2.png"> <img src="images/loading.gif" data-src="images/3.png"> <img src="images/loading.gif" data-src="images/4.png"> <img src="images/loading.gif" data-src="images/5.png"> <img src="images/loading.gif" data-src="images/6.png"> <img src="images/loading.gif" data-src="images/7.png"> <img src="images/loading.gif" data-src="images/8.png"> <img src="images/loading.gif" data-src="images/9.png"> <img src="images/loading.gif" data-src="images/10.png"> <img src="images/loading.gif" data-src="images/11.png"> <img src="images/loading.gif" data-src="images/12.png"> <script> function lazyload() { var images = document.getElementsByTagName('img'); var len = images.length; var n = 0; //存储图片加载到的位置,避免每次都从第一张图片开始遍历 return function() { var seeHeight = document.documentElement.clientHeight; var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; for(var i = n; i < len; i++) { if(images[i].offsetTop < seeHeight + scrollTop) { if(images[i].getAttribute('src') === 'images/loading.gif') { images[i].src = images[i].getAttribute('data-src'); } n = n + 1; } } } } var loadImages = lazyload(); loadImages(); //初始化首页的页面图片 window.addEventListener('scroll', loadImages, false); </script> </body> </html>
比较 image 的 offsetTop 与 seeHeight + scrollTop 的大小,当小于时则说明图片已经出现过在视口中,这时候继续判断图片是否已经替换过,若是没有替换过,则进行替换。性能
实现的效果:不断滑动页面时,图片延迟加载code
你能够拷贝个人代码去进行实验,可是请确保 HTML 同目录下有 images 目录而且含有 1~12.png 和 loading.gif。server
须要说起的是变量 n 是用来保存已经加载的图片数量,避免每次都从第一张图片开始遍历,提高性能。上面的代码用到了 JS 闭包的知识,若是你不太熟悉的话,能够自行百度一下。
第二种:
上面的代码是没什么问题,可是性能误差。若是直接将函数绑定在 scroll 事件上,当页面滚动时,函数会被高频触发,这很是影响浏览器的性能。我粗略地估计一下,当简单地滚动一下页面,函数至少触发了十来次,这显然是十分不必的。
因此在作事件绑定的时候,能够对 lazyload 函数进行函数节流(throttle)与函数去抖(debounce)处理。
这里我并再也不另外介绍这两种方案,若是你想了解的话能够阅读:JS魔法堂:函数节流(throttle)与函数去抖(debounce) - ^_^肥仔John - 博客园
简单说来:
下面就是通过 throttle 处理后的代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Lazyload 2</title> <style> img { display: block; margin-bottom: 50px; height: 200px; } </style> </head> <body> <img src="images/loading.gif" data-src="images/1.png"> <img src="images/loading.gif" data-src="images/2.png"> <img src="images/loading.gif" data-src="images/3.png"> <img src="images/loading.gif" data-src="images/4.png"> <img src="images/loading.gif" data-src="images/5.png"> <img src="images/loading.gif" data-src="images/6.png"> <img src="images/loading.gif" data-src="images/7.png"> <img src="images/loading.gif" data-src="images/8.png"> <img src="images/loading.gif" data-src="images/9.png"> <img src="images/loading.gif" data-src="images/10.png"> <img src="images/loading.gif" data-src="images/11.png"> <img src="images/loading.gif" data-src="images/12.png"> <script> function throttle(fn, delay, atleast) { var timeout = null, startTime = new Date(); return function() { var curTime = new Date(); clearTimeout(timeout); if(curTime - startTime >= atleast) { fn(); startTime = curTime; }else { timeout = setTimeout(fn, delay); } } } function lazyload() { var images = document.getElementsByTagName('img'); var len = images.length; var n = 0; //存储图片加载到的位置,避免每次都从第一张图片开始遍历 return function() { var seeHeight = document.documentElement.clientHeight; var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; for(var i = n; i < len; i++) { if(images[i].offsetTop < seeHeight + scrollTop) { if(images[i].getAttribute('src') === 'images/loading.gif') { images[i].src = images[i].getAttribute('data-src'); } n = n + 1; } } } } var loadImages = lazyload(); loadImages(); //初始化首页的页面图片 window.addEventListener('scroll', throttle(loadImages, 500, 1000), false); </script> </body> </html>
设置了 500ms 的延迟,和 1000ms 的间隔,当超过 1000ms 未触发该函数,则当即执行该函数,否则则延迟 500ms 执行该函数。
实现效果:能够看出有必定的延迟。
参考连接:实现图片懒加载(lazyload)
第三种: 使用 IntersectionObserver API
目前有一个新的 IntersectionObserver API,能够自动"观察"元素是否可见,Chrome 51+ 已经支持。
这里不过多介绍 IntersectionObserver API 的详细使用,感兴趣能够另外阅读下面的文章:
IntersectionObserver API 使用教程
Intersection Observer API
实现代码:简洁,可是浏览器还没有所有实现。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Lazyload 3</title> <style> img { display: block; margin-bottom: 50px; width: 800px; } </style> </head> <body> <img src="images/loading.gif" data-src="images/1.png"> <img src="images/loading.gif" data-src="images/2.png"> <img src="images/loading.gif" data-src="images/3.png"> <img src="images/loading.gif" data-src="images/4.png"> <img src="images/loading.gif" data-src="images/5.png"> <img src="images/loading.gif" data-src="images/6.png"> <img src="images/loading.gif" data-src="images/7.png"> <img src="images/loading.gif" data-src="images/8.png"> <img src="images/loading.gif" data-src="images/9.png"> <img src="images/loading.gif" data-src="images/10.png"> <img src="images/loading.gif" data-src="images/11.png"> <img src="images/loading.gif" data-src="images/12.png"> <script> function query(selector) { return Array.from(document.querySelectorAll(selector)); } var io = new IntersectionObserver(function(items) { items.forEach(function(item) { var target = item.target; if(target.getAttribute('src') == 'images/loading.gif') { target.src = target.getAttribute('data-src'); } }) }); query('img').forEach(function(item) { io.observe(item); }); </script> </body> </html>
实现效果: