$
别名与其他库发生冲突,可以使用 jQuery ,或者在立即调用的函数表达式(IIFE)中传入 $
,使其成为一个局部变量。$.myPlugin
的方式扩展jQuery,还是以 $.fn.myPlugin
的方式扩展jQuery的原型,给 $
命名空间添加的属性都不要超过一个。更多的公有方法和属性应该添加到插件的命名空间中(例如, $.myPlugin.publicMethod
或 $.fn.myPlugin.plugin Property
)。$.fn.myPlugin.defaults = {size:'large'}
。$.fn.myPlugin.defaults.size = 'medium';
)和单独调用( $('div').myPlugin ({size: 'small'});
)。$.fn.myPlugin
)要返回 this ,以便插件用户通过连缀语法调用其他jQuery方法(如 $('div').myPlugin().find('p').addClass('foo')
)。// 阴影效果
;(function($){
$.fn.shadow = function(opts){
var options = $.extend({}, $.fn.shadow.defaults, opts);
return this.each(function(){
var $originalElement = $(this);
for(var i = 0; i < options.copies; i++){
var offset = options.copyOffset(i);
$originalElement.clone()
.css({
position: 'absolute',
left: $originalElement.offset().left + offset.x,
top: $originalElement.offset().top + offset.y,
margin: 0,
zIndex: -1,
opacity: options.opacity
}).appendTo('body');
}
});
}
// 可定制的默认设置参数
$.fn.shadow.defaults = {
copies: 5,
opacity: 0.1,
copyOffset: function(index){
return {x: index, y:index};
}
};
})(jQuery);
在使用选择符表达式查找元素的时候,jQuery会在一个内部的对象 expr 中取得JavaScript代码。这个对象中的值与我们传入到 .filter() 或 .not() 中的筛选函数非常相似,当且仅当取得的函数返回 true 的情况下,才会让每个元素包含在结果集中。使用 $.extend() 函数可以为这个对象添加新的表达式。
(function($) {
$.extend($.expr[':'], {
group: function(element, index, matches, set) { var num = parseInt(matches[3], 10); if (isNaN(num)) { return false; } return index % (num * 2) <num; }
});
})(jQuery);
以上代码告诉jQuery: group 是一个有效的字符串,可以放在一个冒号的后面构成选择符表达式。而在遇到这个选择符表达式的时候,应该调用给定的函数,用以决定相应的元素是否应该包含在结果集中。
这个被求值的函数一共接收了4个参数。
(1) element :当前考虑的DOM元素。这个参数对于大多数选择符都是必须的,但我们这个选择符则不需要。
(2) index :DOM元素在结果集中的索引。
(3) matches :数组,包含用于解析这个选择符的正则表达式的解析结果。一般来说,matches[3] 是这个数组中唯一有用的值;假设有一个选择符的形式为 :group(b) ,则matches[3] 中包含的值就是 b ,也就是括号中的文本。
(4) set :匹配到当前元素的整个DOM元素集合。这个参数很少用。
伪类选择符需要使用包含在这4个参数中的信息,决定当前元素是否应该包含在结果集中。在我们这个例子中,只需要 index 和 matches 这两个参数。
新添加的jQuery方法应该在操作匹配的元素集之后返回jQuery对象,以便用户可以再连缀其他方法。在创建DOM遍历方法时,这个过程也是类似的,但是返回的jQuery对象必须要指向一个新匹配的元素集。可以通过为 $.fn 添加属性的方式来向jQuery中添加遍历方法。
(function($) {
$.fn.column = function() {
var $cells = $();
this.each(function() { var $td = $(this).closest('td, th'); if ($td.length) { var colNum = $td[0].cellIndex + 1; var $columnCells = $td .closest('table') .find('td, th') .filter(':nth-child(' + colNum + ')'); $cells = $cells.add($columnCells); } });
return this.pushStack($cells);
};
})(jQuery);
如果我们自己要编写的插件会创建新的用户界面元素,通常最好以扩展jQuery UI库的方式来实现。
每个部件都会包含一组复杂的功能,但所幸的是,这们不需要自己承担这些复杂性。jQueryUI库的核心包含了一个工厂方法,叫 $.widget()
,这个方法能帮我们做很多事情。使用这个方法可以确保我们的代码达到所有jQuery UI部件用户认可的API标准。
使用部件工厂创建的插件具有很多不错的特性。只要编写少量代码,就可以额外获得这些功能(甚至更多):
(1) 插件具有了“状态”,可以检测、修改甚至在应用之后完全颠覆插件的原始效果;
(2) 自动将用户提供的选项与定制的选项合并到一起;
(3) 多个插件方法无缝组合为一个jQuery方法,这个方法接受一个表明要调用哪个子方法的字符串;
(4) 插件触发的自定义事件处理程序可以访问部件实例的数据。
事实上,鉴于这些功能如此诱人,在构建任何适当的(无论与UI有关还是无关的)复杂插件时,谁都希望使用部件工厂方法。
// 使用jQuery UI 来创建插件 .tooltip()
(function($) {
$.widget('ljq.tooltip', {
_create: function() {
this._tooltipDiv = $('<div></div>')
.addClass('ljq-tooltip-text ' +
'ui-widget ui-state-highlight ui-corner-all')
.hide().appendTo('body');
this.element
.addClass('ljq-tooltip-trigger')
.on('mouseenter.ljq-tooltip',
$.proxy(this._open, this))
.on('mouseleave.ljq-tooltip',
$.proxy(this._close, this));
},
destroy: function() {
this._tooltipDiv.remove();
this.element
.removeClass('ljq-tooltip-trigger')
.off('.ljq-tooltip');
$.Widget.prototype.destroy.apply(this, arguments);
},
options: {
offsetX: 10,
offsetY: 10,
content: function() {
return $(this).data('tooltip-text');
}
},
open: function() {
this._open();
},
close: function() {
this._close();
},
_open: function() {
if (!this.options.disabled) {
var elementOffset = this.element.offset();
this._tooltipDiv.css({
left: elementOffset.left + this.options.offsetX,
top: elementOffset.top + this.element.height()
+ this.options.offsetY
}).text(this.options.content.call(this.element[0]));
this._tooltipDiv.show();
this._trigger('open');
}
},
_close: function() {
this._tooltipDiv.hide();
this._trigger('close');
}
});
})(jQuery);