尽管现在前端技术发展飞速发展,各种技术迭代很快,但jQuery还是在一些企业站或者简单网页尝尝用到,本文记录一下学写jQuery插件的内容,愿新手共勉,共同进步!
jQuery插件写前了解
jQuery如何工作:jQuery对象方法
在我们编写自己的插件之前,我们必须先了解一下jQuery的工作原理。 看看这段代码:
$( "a" ).css( "color", "red" );
这是一些非常基本的jQuery代码,但你知道幕后发生了什么吗? 每当使用$
函数选择元素时,它都会返回一个jQuery对象。 此对象包含您一直使用的所有方法(.css(),. click()
等)以及适合您的选择器的所有元素。 jQuery对象从$ .fn
对象获取这些方法。 该对象包含所有jQuery对象方法,如果我们想编写自己的方法,则还需要包含这些方法。
基本插件创作
假设我们想要创建一个插件,使一组检索到的元素中的文本变为绿色。 我们所要做的就是在$ .fn中添加一个名为greenify的函数,它就像任何其他jQuery对象方法一样可用。
$.fn.greenify = function() {
this.css( "color", "green" );
};
$( "a" ).greenify(); // Makes all the links green.
请注意,使用this.css()
,而不是$(this)
。 这是因为我们的greenify函数是与.css()
相同的,this就是代表jq取出来的元素集合。
链式操作
我们需要做的一些事情才能使我们的插件在环境中生存。 当您将五个或六个动作链式操作到一个选择器时,jQuery最好用的一个功能就是链式操作。 这是通过让所有jQuery对象方法再次返回原始jQuery对象来实现的(有一些例外:.width()
在没有参数的情况下调用返回所选元素的宽度,并且不可链式操作)。 让我们的插件可以实现链式操作需要一行代码:
$.fn.greenify = function() {
this.css( "color", "green" );
//返回this对象,即可实现链式操作
return this;
}
$( "a" ).greenify().addClass( "greenified" );
$别名保护并添加范围
$
变量在JavaScript库中非常流行,如果你在jQuery中使用另一个库,则必须使jQuery不使用$
with jQuery.noConflict()。 但是,这会破坏我们的插件,因为它是在假设$
是jQuery函数的别名的情况下编写的。 为了与其他插件一起使用,并且仍然使用jQuery $
别名,我们需要将所有代码放在里面并立即调用函数表达式中,然后传递函数jQuery,并将参数命名为$
:
(function ( $ ) {
$.fn.greenify = function() {
this.css( "color", "green" );
return this;
};
}( jQuery ));
此外,立即调用函数的主要目的是允许我们拥有自己的私有变量。 假装我们想要一个不同的颜色绿色,我们想将它存储在一个变量中。
(function ( $ ) {
var shade = "#556b2f";
$.fn.greenify = function() {
this.css( "color", shade );
return this;
};
}( jQuery ));
最大限度地减少插件占用空间
编写插件只占用$ .fn
中的一个插槽是一种很好的做法。 这样可以降低插件被覆盖的可能性,以及插件覆盖其他插件的可能性。
(function( $ ) {
$.fn.openPopup = function() {
// Open popup code.
};
$.fn.closePopup = function() {
// Close popup code.
};
}( jQuery ));
提炼一个公共方法会更好,并使用参数来控制执行不同的操作。
(function( $ ) {
$.fn.popup = function( action ) {
if ( action === "open") {
// Open popup code.
}
if ( action === "close" ) {
// Close popup code.
}
};
}( jQuery ));
使用each()方法
典型的jQuery对象将包含对任意数量的DOM元素的引用,这就是jQuery对象通常被称为集合的原因。 如果要对特定元素进行任何操作(例如,获取数据属性,计算特定位置),则需要使用.each()
循环遍历元素。
$.fn.myNewPlugin = function() {
return this.each(function() {
// Do something to each element here.
});
};
请注意,我们返回.each()
的结果而不是返回它。 因为.each()
已经是可链式操作的,所以它返回它,然后我们再返回。 这是保持可链式操作的一种比我们迄今为止所做的更好的方法。
接受选项
随着您的插件变得越来越复杂,最好通过接受选项来使您的插件可自定义。 最简单的方法是使用对象文字,特别是如果有很多选项的话。 让我们更改我们的greenify插件以接受一些选项。
(function ( $ ) {
$.fn.greenify = function( options ) {
// This is the easiest way to have default options.
var settings = $.extend({
// These are the defaults.
color: "#556b2f",
backgroundColor: "white"
}, options );
// Greenify the collection based on the settings variable.
return this.css({
color: settings.color,
backgroundColor: settings.backgroundColor
});
};
}( jQuery ));
使用#556b2f
的颜色默认值被$ .extend()
覆盖为橙色。
$( "div" ).greenify({
color: "orange"
});
以下是使用我们讨论过的一些技术的小插件示例:
这个方便的插件遍历集合中的所有锚点,并在括号中附加href属性。
(function( $ ) {
$.fn.showLinkLocation = function() {
this.filter( "a" ).each(function() {
var link = $( this );
link.append( " (" + link.attr( "href" ) + ")" );
});
return this;
};
}( jQuery ));
// Usage example:
$( "a" ).showLinkLocation();
<!-- Before plugin is called: -->
<a href="page.html">Foo</a>
<!-- After plugin is called: -->
<a href="page.html">Foo (page.html)</a>
我们的插件可以优化:
(function( $ ) {
$.fn.showLinkLocation = function() {
this.filter( "a" ).append(function() {
return " (" + this.href + ")";
});
return this;
};
}( jQuery ));
我们使用.append()
方法接受回调的功能,该回调的返回值将确定附加到集合中每个元素的内容。 另请注意,我们没有使用.attr()
方法来检索href属性,因为本机DOM API使我们可以使用恰当命名的href属性轻松访问。
jQuery.fn.extend(object)
增加两个插件方法。
jQuery.fn.extend({
check: function() {
return this.each(function() { this.checked = true; });
},
uncheck: function() {
return this.each(function() { this.checked = false; });
}
});
$("input[type=checkbox]").check();
$("input[type=radio]").uncheck();
你可以拓展一个对象到jQuery的 prototype里去,这样的话就是插件机制了。
(function($) {
$.fn.tooltip = function(options) {};
//等价于 var
tooltip = {
function(options) {}
};
$.fn.extend(tooltip) = $.prototype.extend(tooltip) = $.fn.tooltip
})(jQuery);
jQuery.fn.extend()的调用把方法扩展到了对象的prototype上,所以实例化一个jQuery对象的时候,它就具有了这些方法,在jQuery.JS中到处体现这一点。
Object jQuery.extend( target, object1, [objectN])
用一个或多个其他对象来扩展一个对象,返回被扩展的对象
jQuery.extend(object)
为jQuery类添加类方法,可以理解为添加静态方法。如:
jQuery.extend({
min: function(a, b) { return a < b ? a : b; },
max: function(a, b) { return a > b ? a : b; }
});
jQuery.min(2,3); // 2
jQuery.max(4,5); // 5
jQuery.extend( target, object1, [objectN])
用一个或多个其他对象来扩展一个对象,返回被扩展的对象
var settings = { validate: false, limit: 5, name: "foo" };
var options = { validate: true, name: "bar" };
jQuery.extend(settings, options);
结果:settings == { validate: true, limit: 5, name: "bar" }
jQuery.fn.extend(object);
对jQuery.prototype进得扩展,就是为jQuery类添加“成员函数”。jQuery类的实例可以使用这个“成员函数”。
jQuery.fn.extend = jQuery.prototype.extend
你可以拓展一个对象到jQuery的 prototype里去,这样的话就是插件机制了。
(function( $ ){
$.fn.tooltip = function( options ) {
};
//等价于
var tooltip = {
function(options){
}
};
$.fn.extend(tooltip) = $.prototype.extend(tooltip) = $.fn.tooltip;
})( jQuery );
插件通用模板
// 包一层匿名函数防止污染
;(function(window,$,undefined){
$.fn.extend({
// plugName
'plugName': function(option){
// option 是用户调用插件时候传入的参数
// defaults 是插件的默认参数
// opts 是根据用户传入的参数与默认值合并之后的实际参数
var defaults = {
},
opts = $.extend({}, defaults, option);
//循环所有jq元素集合,执行这个回调函数,这里的this是一个元素集合,就是用jq获取的那个元素集合,所以要在这里循环一下执行回调
this.each(function(){
// 插件需要的任何操作
});
//返回jq对象里的每一个元素,可以进行链式操作,当然如果不希望在插件后继续链式操作也可以不返回这个this
return this;
}
});
})(window,jQuery);
如何写一个jQuery插件:
- 把上面插件通用模板代码复制到一个新建的js文件里
plugName
改成插件名字- 把插件逻辑变量写到变量
defaults
里 this.each
的回调函数里写上插件的代码逻辑
这样一个简单的jQuery就搞定了,是不是非常简单!