由於網頁設計目前用到jQuery的機率越來越高,常常寫了一段程式碼需要重複使用,於是決定把它製作成模組使用
建立一個Plugin
(function($){
$.fn.helloworld = function(){
alert('Hello World');
}
})(jQuery);
照jQuery文件說明,是可以這樣寫
jQuery.fn.helloworld = function(){
alert('Hello World');
}
不過一方面為了方便使用「$」字號,且不與其他函式庫衝突,所以就使用外層包著,這樣就可以在裡面使用「$」字號,不會衝突。
this代表的意義
假設我們這麼寫了一段程式碼
(function($){
$.fn.showbox = function(){
this.fadeIn('slow');
}
})(jQuery);
然後我們只要這樣使用
$('div').showbox();
div就會依照Plugin內的程式碼去執行,this就等於div這個物件,不需再另外再去指定。
保持鏈結(Maintaing Chainability)
下面有個範例<取自jQuery網站>
(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');
照上面的範例,因為這個物件必須接著下面繼續的動作,所以在lockDimensions這個plugin必須回傳this,才能繼續接著.css()這類其他jQuery的函式,要是沒有回傳this的話,就會接不到物件,而後面動作都沒有效果。
設定預設值和選項(Defaults and Options)
許多功能性較複雜的plugin,會給予使用者很多選項去選擇所需的功能,來符合自己的需求,而這些選項必然需要預設值來確保plugin的運作正常,當使用者忘記給予一些參數時,預設值能自動替補上去,來讓程式運行正常。
(function( $ ){
$.fn.box = function( options ) {
//設定選項和預設值
var settings = $.extend( {
'width' : '200px',
'height' : '200px',
'background-color' : 'blue'
}, options);
return this.each(function() {
alert(settings.width);
});
};
})( jQuery );
$("div").box();
//200px
$("div").box(
{
'width': 300px
}
};
//300px
在沒有給予選項狀態下,plugin預設會使用程式碼編寫時的預設值。
預設值是一個非常重要的東西,常常再編寫程式碼時忘記給予參數造成程式掛點,如果有設定預設值,就算忘記給予參數,也可以讓程式順利執行。
命名(Namespacing)
這段是jQuery文件中提到的,我也非常認同好的且正確的命名plugin是應該做的事情,其實這也不也僅限於jQuery Plugin而已,在任何程式碼中正確的命名都是必須的,最好用幫自己小孩取名子的心態下去取,總不會把自己的小孩叫a,b,c這類的名稱吧,文件中提到正確的命名可以將名稱衝突的機率降到最低,避免太多隻plugin一起引入時,因為不好的命名結果造成覆蓋,程式無法正確執行,另一方面,正確的命名可以方便開發者快速的追蹤問題,這是非常重要的,畢竟時間就是金錢,因為今天自己的命名不小心結果造成要花更大的成本去檢查錯誤,最後發現命名衝突,這該有多嘔。
多種方法(Plugin Methods)
有的時候我們在寫一隻plugin,會有許多方法可以讓使用者可以選擇,但是每種方法都寫一隻plugin又太多餘,且難以維護管理,且互相都有相依性,這時候就可以這樣寫。
(function($){
var methods = {
init : function( options ) {
var settings = $.extend({
'width': '200px'
},options);
this.css('width', settings.width);
},
show : function( ) {
this.show();
},
hide : function( ) {
this.hide();
},
spin : function( content ) {
alert(content);
}
};
$.fn.box = 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").box();
//call init function;
//set box width 200px.
$("div").box({width: '377px'});
//call init function with options
//set box width 377px.
$("div").box('hide');
//call hide funtion
//div hide
$("div").box('spin', 'This is box.');
//call spin function with argument
//This is box.
這樣就可以依照參數的不同去執行不同的動作,然後又屬於同一隻plugin內,不需要為每種動作都建立一個plugin,我覺得很方便。
事件(Events)
在寫plugin時,一定會用到許多事件問題,常常要綁定一些事件,例如:「click」「blur」這類的事件要處理,在有些情況下,必須要讓這些事件停止動作,我們就必須「unbind」這些事件。所以我們常常會這樣:
(function($){
var methods = {
init: function() {
return this.each(function(){
$(window).bind('click', methods.start);
//未加入namespacing
);
},
stop: function() {
return this.each(function(){
$(window).unbind('click');
//有可能干擾到其他相同類型事件
});
},
start: function(){
..........
}
}
$.fn.runner = 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);
如果照上面那樣寫的話,在初始化runner這個物件時,會綁定click事件,這沒有甚麼太大問題,但是當執行stop時,避免unbind「click」時干擾到其他事件,所以我們可以這樣寫:
var methods = {
init: function() {
return this.each(function(){
$(window).bind('click.runner', methods.start);
//加入了namespacing
);
},
stop: function() {
return this.each(function(){
$(window).unbind('click.runner');
//或是 $(window).unbind('.runner');
//這樣就不會影響其他的事件
});
},
start: function(){
..........
}
}
$.fn.runner = 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' );
}
};
這樣寫的話就可以緊限於這個物件的事件,而不去影響到其他plugin物件的運作。
沒有留言:
張貼留言