前文有簡單的實現了一個制作懶加載的方法,但其實以方法的形式做插件擴展性不強。那么本文就來用面向對象的方法將其制作成一個真正的插件:
我想要的最終的調用效果是:
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