A: 如何實現 Lazy Load?

最近面試了幾家公司,他們不約而同都問到了這個問題:瞭解 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);
相關文章
相關標籤/搜索