天貓首頁迷思之-jquery實現整個div的懶加載(2)-插件面向對象化-閉包和原型的實例


前文有簡單的實現了一個制作懶加載的方法,但其實以方法的形式做插件擴展性不強。那么本文就來用面向對象的方法將其制作成一個真正的插件:

我想要的最終的調用效果是:

1 $(".loading").lazyLoadDiv_cc({
2      //自定義效果,可不填
3     "beginHeight":400,
4     "loadingBgClass":"loading",
5     "whenToLoad":"someIn"
6 });

分析一下,需要擴展jquery的實例如:$(".loading")的方法。插件肯定要用到$這個方法。所以初步原型是:

1 ;(function($){
2     $.fn.lazyLoad=function(this,options){
3          //處理代碼
4     };
5   })(jQuery);

你可能會問的問題:

  • 為什么前面加封號? 答:防止該插件之前的代碼忘記加封號。影響代碼解析;
  • 為什么使用匿名函數?答:寫js的一個原則是盡量不要污染全局變量。插件如果足夠龐大,肯定把所有屬性和方法都暴露給全局。由於js中沒有語句的塊級作用域,所以這里使用立即執行的匿名函數。將不需要暴露給全局,但是插件的邏輯要用到得部分代碼放到函數的局部作用域中。這樣就不會和其他的插件命名沖突啦。
  • 為什么參數要傳jQuery?答:這里其實不傳也不會報錯,但是為了保證代碼的獨立性,傳一下其實更保險。類似window,document這種都可以傳進來。

tips:這里見縫插針,說下jquery和jquery的原型。

  1.$是什么?

  從jquery源碼開始分析:

      第一次出現jQuery:

  

  由圖得知,jquery是一個函數。函數的入參是selector和context,返回一個實例。

  So,$("#div2")是一個實例,擁有很多方法,方法大部分在jQuery原型里面。

 

  暴露給全局變量:

        

  可知$和jQuery其實是同一個函數。

  

  2.$.fn是什么?

  源碼中:

jQuery.fn = jQuery.prototype=$.fn

  所以它是jQuery和$對象的原型。在它里面添加方法相當於$的實例(如$("#div1"))都能調用到。

---------------------------------------------我是一個分割線-------------------------------------------

言歸正傳,初步的模型並沒有用到面向對象的特性。當插件越來越龐大時,面向過程就會變得邏輯混亂,難於管理,難於擴展。so。咱們再改一下

 1 ;(function($){
 2     var lazyloadPlugin=function(ele,opt){
 3         this.elements=ele?ele:$(".loading"),//若沒有第一個參數,默認獲取class為loading的元素
 4         this.defaults={
 5             //參數的默認值
 6             "beginHeight":0,
 7             "howToLoad":"fadeIn",
 8             "loadingBgClass":"loading",//定義未加載前背景圖片的類名
 9             "whenToLoad":"allIn"//默認為div全部在可視窗口內開始加載;其他值:“someIn”
10         },
11         this.options=$.extend({},this.defaults,opt)
12     };
13     lazyloadPlugin.prototype={
14         bindLazy:function(){
15          //實現代碼
16         }
17     };
18     //以上相當於MVC中的模型層,不需要關心邏輯怎么串起來
19     $.fn.lazyLoadDiv_cc=function(options){
20                //相當於MVC中的業務邏輯層,需要組織邏輯
21         var llp=new lazyloadPlugin(this,options);
22         return llp.bindLazy();
23     };
24 })(jQuery);
lazyloadPlugin是定義在匿名函數中的對象,除了調用lazyLoadDiv_cc方法,並沒有其他方式可以使用它。因此它的各種屬性和方法都很安全。特別是它的原型,因為實例沒有辦法改變原型,所以原型中的方法是不可修改的,很安全。
通過這一層封裝,我們只暴露出來了一個看似簡單的方法。卻實現了可擴展、獨立性強、保證性能的方法。
1.可擴展性。
  通過options入參,可以實現不同用戶的需求。例如options中的whenToLoad字段,可以通過定義不同的值,讓插件在不同的位置觸發懶加載。
同時,options在構造函數中定義了默認值。更健壯。
2.獨立性強
  將大部分屬性封裝起來,通過匿名函數+閉包,讓代碼更簡潔安全
3.保證性能
  根據共享的放在原型中,不共享的放在構造函數中這一原則。將默認值都放在對象的構造函數中,而方法的實現放在原型中。方法部分的內存共享,提高性能。

只是一個簡單的例子,就用到了原型、閉包、this、匿名函數等多個知識點,多多實踐比只看書真的好多啦。
實現邏輯之后,網上有在線壓縮工具。所謂壓縮,只是把變量語義化的名字名字改為更短的,多行也改為了一行,文件體積確實是壓縮了,但是邏輯一點也沒少哦。
本次插件地址:
壓縮后-https://github.com/HappyBangs/bang_plugins/blob/master/plugin_TmallLazyLoad/version2.0/lazyload_pcc.min.js
   壓縮前-https://github.com/HappyBangs/bang_plugins/blob/master/plugin_TmallLazyLoad/version2.0/lazyload_pcc.js

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM