最近面试了几家公司,他们不约而同都问到了这个问题:了解 Lazy Load 吗?php
Lazy Load is delays loading of images in long web pages. Images outside of viewport are not loaded until user scrolls to them. This is opposite of image preloading. html
Using Lazy Load on long web pages will make the page load faster. In some cases it can also help to reduce server load.web
Lazy Load实际上是对图片的一种延迟加载技术,直到用户滚动图片出如今用户可视范围时才把它加载出来。它与图片预加载技术彻底相反,却都是为了提升用户体验而设计。面试
Lazy Load Plugin for jQuery - Mika Tuupolachrome
jQuery的Lazy Load插件你们应该都有了解或者已经使用过了。下面是一个简单的栗子:app
<img class="lazy" data-original="img/example.jpg" width="640" height="480"> $(function() { $("img.lazy").lazyload();//能够传入自定义的参数 });
data-original
属性值是咱们想要显示的图片的URL,当用户滚动页面,图片出如今视线范围内时,替换img
元素的src
属性值为data-original
属性值。ide
不过仅仅了解这些好像远远不够。我在网上查找了一些Lazy Load的实现原理,发现了如下的代码:this
// 原生JS实现方法 <script> var imgs = document.getElementsByTagName('img'); // 获取视口高度与滚动条的偏移量 function lazyload(){ // 获取当前滚动条偏移量 var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop; // 获取视口高度 var viewportSize = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; for(var i=0; i<imgs.length; i++) { var x =scrollTop+viewportSize-imgs[i].offsetTop; if(x>0){ imgs[i].src = imgs[i].getAttribute('loadpic'); } } } setInterval(lazyload,1000); </script>
这位老铁本身写了一段简陋的实现代码,他用了定时器循环调用lazyload方法,固然你们能够先忽略,重点看一下如何获取当前滚动条的位置和视口的高度。.net
var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
这个东西我刚看也是一头雾水。我在chrome上亲身实践了一下,然而发现,document.documentElement.scrollTop
老是返回0,其余两种方法都正常获取到了值。因而查了一下才知道这三个获取滚动条位置的方法背后还有故事。看这个问题:插件
document.documentElement.scrollTop return value differs in Chrome
还有其中一位老铁的回答:
The standards-based way of getting the scroll is window.scrollY. This is supported by Chrome, Firefox, Opera, Safari and IE Edge or later. If you only support these browsers, you should go with this property.
IE >= 9 supports a similar property window.pageYOffset, which for the sake of compatibility returns the same as window.scrollY in recent browsers, though it may perhaps be deprecated at some point.
The problem with using document.documentElement.scrollTop or document.body.scrollTop is that the scroll needn't be defined on either of these. Chrome and Safari define their scroll on the <body> element whilst Firefox defines it on the <html> element returned by document.documentElement, for example. This is not standardized, and could potentially change in future versions of the browsers. However, if the scrollY or pageYOffset are not present, this is the only way to get the scroll.
window.scrollY || window.pageYOffset || document.body.scrollTop + (document.documentElement && document.documentElement.scrollTop || 0)
那这故事我就不讲了。
var viewportSize = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
这行代码是为了获取视口的高度,咱们一样看到了三种方法,那他们背后确定也有不为我知的故事,如今我也不太想知道了。
var x =scrollTop+viewportSize-imgs[i].offsetTop;
如何得到一个元素与页面顶端的距离,你学会了吗?
下面是用jQuery实现的lazyload,也是刚才那位老铁写的:
/** * 图片的src实现原理 */ $(document).ready(function(){ // 获取页面视口高度 var viewportHeight = $(window).height(); var lazyload = function() { // 获取窗口滚动条距离 var scrollTop = $(window).scrollTop(); $('img').each(function(){ // 判断 视口高度+滚动条距离 与 图片元素距离文档原点的高度 var x = scrollTop + viewportHeight - $(this).position().top; // 若是大于0 即该元素能被浏览者看到,则将暂存于自定义属性loadpic的值赋值给真正的src if (x > 0) { $(this).attr('src',$(this).attr('loadpic')); } }) } // 建立定时器 “实时”计算每一个元素的src是否应该被赋值 setInterval(lazyload,100); });
上述的实现呢,我感受仍是能够说服个人,把定时器去掉,加入对滚动事件的侦听便可。不过,就这么草草了事好像也没什么意思,我下载了jQuery-lazyload的源码,准备研究一波。若是我看懂了什么,或者有什么收获,再来聊聊。
/*! * Lazy Load - jQuery plugin for lazy loading images * * Copyright (c) 2007-2015 Mika Tuupola * * Licensed under the MIT license: * http://www.opensource.org/licenses/mit-license.php * * Project home: * http://www.appelsiini.net/projects/lazyload * * Version: 1.9.7 * */ (function($, window, document, undefined) { // body... })(jQuery, window, document);