能够经过为jQuery.fn增长一个新的函数来编写jQuery插件。属性的名字就是你的插件的名字:css
jQuery.fn.myPlugin = function(){
//开始写你的代码吧!
};
复制代码
可是,那惹人喜好的美圆符号$
哪里去了?她就是jQuery,可是为了确保你的插件与其余使用$
的库不冲突,最好使用一个当即执行的匿名函数,这个匿名函数的参数是jQuery,这样其余的库就能够放心的使用$
符号了。闭包
(function( $ ){
$.fn.myPlugin = function() {
// 开始吧!
};
})( jQuery );
复制代码
这样更好了就。在闭包内,能够放心的使用$符号了~app
如今已经能够编写咱们的代码了,可是编写以前,我必须说一说上下文。在插件内部的范围中,this关键字指向的是jQuery对象。人们很容易误解这一点,由于在正常使用jQuery的时候,this一般指向的是一个DOM元素。不了解这一点,会常用$又包装了一次。ide
(function( $ ){
$.fn.myPlugin = function() {
// 没有必要使用$(this)
// $(this) 跟 $($('#element'))是同样的
this.fadeIn('normal', function(){
//这里的this指的就是一个DOM元素了
});
};
})( jQuery );
$('#element').myPlugin();
复制代码
接下来写一个能用的插件吧。函数
(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
上一个例子是返回了一个整数,可是大多数状况下,一个插件牢牢是修改收集到的元素,而后返回这个元素让链条上的下一个使用。这是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
为了一些复杂的,可订制的插件,最好提供一套默认值,在被调用的时候扩展默认值。这样,调用函数的时候就不用传入一大堆参数,而是传入须要被替换的参数。你能够这样作:插件
(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'。这样能够保证高度可配置性,而不须要开发者定义全部可能的选项了。设计
正确的命名空间对于插件开发十分重要,这样能确保你的插件不被其余插件重写,也能避免被页面上其余代码重写。命名空间可使你更长寿,由于你能记录你本身的方法,事件,数据等。 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附上多个函数 ● 为你的函数,事件,数据附着到某个命名空间