圖片延遲加載demo

Talk is cheap,show me the Code~先上代碼,再說心路

/**
 * lazyload demo
 * 
 */
(function($, window, document, undefined) {
    $.fn.Lazyload = function(opts) {
        var elements = this,
            timer = false,
            defaults = {
                data_attribute: 'data-src',
                threshold: 0
            },
            options = $.extend({}, defaults, opts);
        //最初進入頁面從所有元素中篩選出在視區(qū)內(nèi)的元素執(zhí)行任務
        bindEvents();
        //滾動事件停止后視區(qū)內(nèi)的元素執(zhí)行任務
        $(window).on("scroll", function() {
            if (timer) { clearTimeout(timer); }
            timer = setTimeout(bindEvents, 1000);
        })

        function bindEvents() {
            elements.each(function() {
                var me = this;
                me.loaded = false; //將所有元素標記為  未執(zhí)行任務,執(zhí)行過appear()的元素該屬性就會標記為true
                if (checkIsInView(me)) {
                    appear(me);
                }
            });
            //將元素列表的更新放到一屏結束后統(tǒng)一更新一次
            var temp = $.grep(elements, function(element) {
                return (!element.loaded);
            })
            elements = $(temp);

        };

        function checkIsInView(element) {
            var isAboveTheView,
                isBelowTheView,
                $window = $(window);

            isAboveTheView = ($(element).offset().top + $(element).height() + options.threshold < $window.scrollTop()) ? true : false;
            isBelowTheView = ($(element).offset().top - options.threshold > $window.scrollTop() + $window.height()) ? true : false;
            if (!isBelowTheView && !isAboveTheView) {
                return true;
            } else {
                return false;
            }
        };

        function appear(element) {
            var data_src = $(element).attr(options.data_attribute);
            $(element).attr("src", data_src);
            element.loaded = true;
        };

    }
})(window.jQuery, window, document);

心路歷程&查漏補缺

1、模式的轉(zhuǎn)變

最開始使用了構造函數(shù)加原型的混合模式,但是后來發(fā)現(xiàn)這樣寫很有問題(當然很有可能是我掌握不精所致),直接?把這個完整的方法賦給每個元素,不容易將執(zhí)行完任務的元素從待執(zhí)行任務的元素列表中移除,所以后來改成了單例模式,然后這個就越看越像是jquery.lazyload.js的極簡版。
那么總結下思路的轉(zhuǎn)變過程:

滾動停止后對所有元素都去判斷是否在視區(qū),執(zhí)行相應任務——改為——滾動停止后從待執(zhí)行任務的元素列表中搜索留在視區(qū)內(nèi)的元素,顯示。

另外,在模式轉(zhuǎn)變的過程中函數(shù)方法的定義方式也要發(fā)生改變,這使得我對原型函數(shù)中的對象方法有了進一步的認識。我們都知道在js中一切都是對象,對象方法和對象屬性沒什么不同,只是前者的值是函數(shù)而已,所以原型函數(shù)中的對象方法看起來也都是鍵值對的樣子。想訪問該屬性,當做字符串訪問,想調(diào)用該方法加(),如:

var person = {
    firstName: "John",
    lastName : "Doe",
    id       : 5566,
    fullName : function() {
       return this.firstName + " " + this.lastName;
    }
};
console.log(person.fullName);//function() { return this.firstName + " " + this.lastName;}
console.log(person.fullName());//John Doe

2、更新元素列表這項工作放到哪兒執(zhí)行更好?

每個元素的圖片被替換之后就立即更新列表,還是這一屏的元素的圖片都替換完了之后再統(tǒng)一更新一次?這兩者哪個耗時更短?前者是篩選次數(shù)執(zhí)行的多,后者是查找的次數(shù)執(zhí)行的多,個人從理論上分析,篩選是要更耗時的,因為一次篩選過程要查找然后更新新數(shù)組(不管其內(nèi)部用的是數(shù)組還是指針都要多幾步的,那么對于數(shù)組元素的刪除、過濾其內(nèi)部是如何實現(xiàn)的還有待考究)。所以我是在一屏的圖片被替換后更新一次元素列表。

這是更新數(shù)組的代碼:

      var temp=$.grep(elements,function(element){
            return (!element.loaded);//最開始遍歷元素的時候給每個元素設置一個屬性loaded作為標志位
       })
       elements=temp;

3、添加限制條件:滾動停止后才執(zhí)行替換圖片的任務

這一知識也是聽師父介紹的,這個在淘寶無線端有應用。這兒利用setTimeout來判斷滾動事件停止,滾動過程中不去加載。(像移動端有區(qū)分touchStart,touchEnd事件就不用這么麻煩了)

 $(window).on("scroll", function() {
     if (timer) { clearTimeout(timer); }
     timer = setTimeout(bindEvents, 1000);
 })

最開始的時候把timer定義在了scroll事件里,然后就理所當然的發(fā)生里一些不可思議的事情。。。真是粗心大意害死人。

4、獲取到文檔頂部距離

jquery中獲取元素到文檔頂部的距離:$().offset().top
當前視口到文檔頂部的距離: scrollTop()
原生javascript中只能獲取相對父元素的left,top,那么是如何獲得距離文檔頂部的距離的?
一層層遞歸到父元素為body

function getOffsetTop(element){
  var actualTop = element.offsetTop;
  var current = element.offsetParent;
  while (current !== null){
    actualTop += current.offsetTop;
    current = current.offsetParent;
  }
  return actualTop;
}
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,094評論 25 709
  • 發(fā)現(xiàn) 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 15,401評論 4 61
  • 很多時候我們感到害怕和不想嘗試新的挑戰(zhàn),是因為對未知事物的恐懼,第一天的訓練強度很大,但今天已經(jīng)基本適應,或者說從...
    FAB蘋果閱讀 210評論 0 0
  • 凌亂 瀲滟的 唇 閃動的 波光 風卷著 柳絮 如雪 輕墜 瞬間的凝固 從指縫間 旋舞 纏繞 心 不再 跳動 編號:...
    Keya的意識空間閱讀 178評論 0 2

友情鏈接更多精彩內(nèi)容