深刻理解jQuery插件開發總結(二)

1,開始

能夠經過爲jQuery.fn增長一個新的函數來編寫jQuery插件。屬性的名字就是你的插件的名字:css

jQuery.fn.myPlugin = function(){  
      //開始寫你的代碼吧!  
  };  
複製代碼

可是,那惹人喜好的美圓符號$哪裏去了?她就是jQuery,可是爲了確保你的插件與其餘使用$的庫不衝突,最好使用一個當即執行的匿名函數,這個匿名函數的參數是jQuery,這樣其餘的庫就能夠放心的使用$符號了。閉包

(function( $ ){  
     $.fn.myPlugin = function() {  
       // 開始吧!  
     };  
   })( jQuery );  
複製代碼

這樣更好了就。在閉包內,能夠放心的使用$符號了~app

2,上下文

如今已經能夠編寫咱們的代碼了,可是編寫以前,我必須說一說上下文。在插件內部的範圍中,this關鍵字指向的是jQuery對象。人們很容易誤解這一點,由於在正常使用jQuery的時候,this一般指向的是一個DOM元素。不瞭解這一點,會常用$又包裝了一次。ide

(function( $ ){  
     $.fn.myPlugin = function() {  
      // 沒有必要使用$(this)  
      // $(this) 跟 $($('#element'))是同樣的    
     this.fadeIn('normal', function(){  
      //這裏的this指的就是一個DOM元素了  
     });  
   };  
 })( jQuery );     
$('#element').myPlugin();  
複製代碼

3,基本開發

接下來寫一個能用的插件吧。函數

(function( $ ){  
    $.fn.maxHeight = function() {  
      var max = 0;  
      this.each(function() {  
        max = Math.max( max, $(this).height() );  
      });  
      return max;  
    };  
  })( jQuery );  
  var tallest = $('div').maxHeight();  
複製代碼

這是一個簡單的插件,經過調用height()返回頁面上height最大的div的height。this

4,維護鏈式開發的特性

上一個例子是返回了一個整數,可是大多數狀況下,一個插件牢牢是修改收集到的元素,而後返回這個元素讓鏈條上的下一個使用。這是jQuery設計的精美之處,也是jQuery如此流行的緣由之一。爲了保證可鏈式,你必須返回this。spa

(function( $ ){  
   $.fn.lockDimensions = function( type ) {    
     return this.each(function() {  
       var $this = $(this);  
       if ( !type || type == 'width' ) {  
        	$this.width( $this.width() );  
      	 }  
      if ( !type || type == 'height' ) {  
         $this.height( $this.height() );  
    	  }  
     });  
  };  
  })( jQuery );  
  $('div').lockDimensions('width').css('color','red');  
複製代碼

由於該插件返回了this,因此保證了可鏈式,從而能夠繼續使用jQuery方法進行修改,如css()。若是你的插件若是不是返回一個簡單值,你一般應該返回this。並且,正如你可能想到的,你傳進去的參數也能夠在你的插件中訪問。因此在這個例子中,能夠訪問到type。prototype

5,默認值和選項

爲了一些複雜的,可訂製的插件,最好提供一套默認值,在被調用的時候擴展默認值。這樣,調用函數的時候就不用傳入一大堆參數,而是傳入須要被替換的參數。你能夠這樣作:插件

(function( $ ){  
   $.fn.tooltip = function( options ) {    
    var settings = {  
       'location'         : 'top',  
      'background-color' : 'blue'  
    };  
     return this.each(function() {          
      // 若是存在選項,則合併之  
       if ( options ) {   
         $.extend( settings, options );  
      }  
      // 其餘代碼咯  
     });  
  };  
 })( jQuery );  
$('div').tooltip({'location':'left'});  
複製代碼

在這個例子中,調用插件後,默認的location會被替換城'left',而background-color仍是'blue'。這樣能夠保證高度可配置性,而不須要開發者定義全部可能的選項了。設計

6,命名空間

正確的命名空間對於插件開發十分重要,這樣能確保你的插件不被其餘插件重寫,也能避免被頁面上其餘代碼重寫。命名空間可使你更長壽,由於你能記錄你本身的方法,事件,數據等。 a,插件方法 在任何狀況下,都不要在一個插件中爲jQuery.fn增長多個方法。如:

(function( $ ){  
   $.fn.tooltip = function( options ) { // 這樣 };  
   $.fn.tooltipShow = function( ) { // 是   };  
   $.fn.tooltipHide = function( ) { // 很差的  };  
   $.fn.tooltipUpdate = function( content ) { // 同窗!  };  
 })( jQuery );  
複製代碼

不推薦這樣使用,搞亂了$.fn命名空間。要糾正之,你能夠把全部的方法放進一個對象中,而後經過不一樣的參數來調用。

(function( $ ){   
  var methods = {  
     init : function( options ) { // THIS },  
     show : function( ) { // IS   },  
     hide : function( ) { // GOOD },  
     update : function( content ) { // !!! }  
  };  
  $.fn.tooltip = function( method ) {  
     // Method calling logic  
     if ( methods[method] ) {  
       return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));  
      } else if ( typeof method === 'object' || ! method ) {  
      return methods.init.apply( this, arguments );  
      } else {  
       $.error( 'Method ' +  method + ' does not exist on jQuery.tooltip' );  
     }      
   };  
 })( jQuery );  
 
 $('div').tooltip({  // calls the init method  
  foo : 'bar'  
 });  
 $('div').tooltip('hide'); // calls the hide method  
 $('div').tooltip('update', 'This is the new tooltip content!'); // calls the update method  
複製代碼

jQuery本身的擴展也是使用這種插件結構。

b,事件 綁定事件的命名空間是比較鮮爲人知的。若是你的插件綁定了某個事件,最好將它搞到一個命名空間中。這樣,若是你之後須要解綁,就不會影響到其餘綁定到這個事件上的函數了。你可使用"."來增長命名空間。

(function( $ ){  
   var methods = {  
      init : function( options ) {  
      return this.each(function(){  
         $(window).bind('resize.tooltip', methods.reposition);  
        });  
     },  
      destroy : function( ) {  
        return this.each(function(){  
         $(window).unbind('.tooltip');  
        })  
     },  
     reposition : function( ) { // ... },  
     show : function( ) { // ... },  
     hide : function( ) { // ... },  
     update : function( content ) { // ...}  
   };  
   $.fn.tooltip = function( method ) {  
    if ( methods[method] ) {  
      return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));  
    } else if ( typeof method === 'object' || ! method ) {  
      return methods.init.apply( this, arguments );  
    } else {  
      $.error( 'Method ' +  method + ' does not exist on jQuery.tooltip' );  
    }      
   };  
  
})( jQuery );    
 $('#fun').tooltip();  
 // Some time later...  
 $('#fun').tooltip('destroy');  
複製代碼

在這個例子中,tooltip在init方法中初始化,它將reposition方法綁定到window對象的resize事件的tooltip名字空間下。稍候,若是開發者須要去掉這個tooltip,咱們能夠解綁這個綁定。這樣就不會影響到其餘綁定到window對象的resize事件的方法了。

c,數據 在開發插件的時候,你一般會有保持狀態或者檢查你的插件是否已經初始化的須要。使用jQuery的data方法是保持變量的很好的方法。可是,咱們不把變量單獨保存,而是放在一個對象中,這樣就能夠在一個名字空間下統一訪問了。

(function( $ ){  
   var methods = {  
      init : function( options ) {     
        return this.each(function(){             
         var $this = $(this),  
             data = $this.data('tooltip'),  
             tooltip = $('<div />', {  
                text : $this.attr('title')  
              });             
          // If the plugin hasn't been initialized yet  
          if ( ! data ) {             
           /* 
              Do more setup stuff here 
            */   
            $(this).data('tooltip', {  
                target : $this,  
               tooltip : tooltip  
           });    
         }  
        });  
      },  
      destroy : function( ) {    
       return this.each(function(){    
          var $this = $(this),  
             data = $this.data('tooltip');  
  
          // Namespacing FTW  
          $(window).unbind('.tooltip');  
          data.tooltip.remove();  
         $this.removeData('tooltip');    
        })    
      },  
      reposition : function( ) { // ... },  
      show : function( ) { // ... },  
      hide : function( ) { // ... },  
      update : function( content ) { // ...}  
   };     
   $.fn.tooltip = function( method ) {         
     if ( methods[method] ) {  
       return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));  
     } else if ( typeof method === 'object' || ! method ) {  
      return methods.init.apply( this, arguments );  
     } else {  
       $.error( 'Method ' +  method + ' does not exist on jQuery.tooltip' );  
    }           
   };  
   
 })( jQuery );  
複製代碼

使用data方法能夠幫助你在插件的各個方法間保持變量和狀態。將各類變量放在一個對象中,能夠方便訪問,也能夠方便移除。 7,總結與最佳實踐 編寫jQuery插件能夠充分利用庫,將公用的函數抽象出來,「循環利用」。如下是簡短的總結:

● 使用(function($){//plugin})(jQuery);來包裝你的插件 ● 不要在插件的初始範圍中重複包裹 ● 除非你返回原始值,不然返回this指針來保證可鏈式 ● 不要用一串參數,而是使用一個對象,而且設置默認值 ● 一個插件,不要爲jQuery.fn附上多個函數 ● 爲你的函數,事件,數據附着到某個命名空間

相關文章
相關標籤/搜索