$.extend({sayHello: function(name) {console.log("Hello," + (name ? name : "Dude") + "!");}})$.sayHello(); //调用$.sayHello("Wayou"); //带参调用
上面代码中,通过$.extend()向jQuery添加了一个sayHello函数,然后通过$直接调用。到此你可以认为我们已经完成了一个简单的jQuery插件了。
但如你所见,这种方式用来定义一些辅助方法是比较方便的。比如一个自定义的console,输出特定格式的信息,定义一次后可以通过jQuery在程序中任何需要的地方调用它。
$.extend({log: function(message) {var now = new Date(),y = now.getFullYear(),m = now.getMonth() + 1, //!JavaScript中月分是从0开始的d = now.getDate(),h = now.getHours(),min = now.getMinutes(),s = now.getSeconds(),time = y + "/" + m + "/" + d + " " + h + ":" + min + ":" + s;console.log(time + " My App: " + message);}})$.log("initializing..."); //调用
但这种方式无法利用jQuery强大的选择器带来的便利,要处理DOM元素以及将插件更好地运用于所选择的元素身上,还是需要使用第二种开发方式。你所见到或使用的插件也大多是通过此种方式开发。
插件开发
下面我们就来看第二种方式的jQuery插件开发。
基本方法
先看一下它的基本格式:
$.fn.pluginName = function() {//your code goes here}$.fn.myPlugin = function() {//在这里面,this指的是用jQuery选中的元素//example :$("a"),则this=$("a")this.css("color", "red");}<ul><li><a href="http://www.webo.com/liuwayong">我的微博</a></li><li><a href="http://http://www.cnblogs.com/Wayou/">我的博客</a></li><li><a href="http://wayouliu.duapp.com/">我的小站</a></li></ul><p>这是p标签不是a标签,我不会受影响</p><script src="jquery-1.11.0.min.js"></script><script src="jquery.myplugin.js"></script><script type="text/javascript">$(function(){$("a").myPlugin();})</script>运行结果:
下面进一步,在插件代码里处理每个具体的元素,而不是对一个集合进行处理,这样我们就可以针对每个元素进行相应操作。
我们已经知道this指代jQuery选择器返回的集合,那么通过调用jQuery的.each()方法就可以处理合集中的每个元素了,但此刻要注意的是,在each方法内部,this指带的是普通的DOM元素了,如果需要调用jQuery的方法那就需要用$来重新包装一下。
比如现在我们要在每个链接显示链接的真实地址,首先通过each遍历所有a标签,然后获取href属性的值再加到链接文本后面。
更改后我们的插件代码为:
$.fn.myPlugin = function() {//在这里面,this指的是用jQuery选中的元素this.css("color", "red");this.each(function() {//对每个元素进行操作$(this).append(" " + $(this).attr("href"));}))}
到此,你已经可以编写功能简单的jQuery插件了。是不是也没那么难。
下面开始jQuery插件编写中一个重要的部分,参数的接收。
支持链式调用
我们都知道jQuery一个时常优雅的特性是支持链式调用,选择好DOM元素后可以不断地调用其他方法。
要让插件不打破这种链式调用,只需return一下即可。
$.fn.myPlugin = function() {//在这里面,this指的是用jQuery选中的元素this.css("color", "red");return this.each(function() {//对每个元素进行操作$(this).append(" " + $(this).attr("href"));}))}让插件接收参数$.fn.myPlugin = function(options) {var defaults = {"color": "red","fontSize": "12px"};var settings = $.extend(defaults, options);return this.css({"color": settings.color,"fontSize": settings.fontSize});}$("a").myPlugin({"color": "#2C9929"});
同时指定颜色与字体大小:
$("a").myPlugin({"color": "#2C9929","fontSize": "20px"});
注意到上面代码调用extend时会将defaults的值改变,这样不好,因为它作为插件因有的一些东西应该维持原样,另外就是如果你在后续代码中还要使用这些默认值的话,当你再次访问它时它已经被用户传进来的参数更改了。

一个好的做法是将一个新的空对象做为$.extend的第一个参数,defaults和用户传递的参数对象紧随其后,这样做的好处是所有值被合并到这个空对象上,保护了插件里面的默认值。
$.fn.myPlugin = function(options) {var defaults = {"color": "red","fontSize": "12px"};var settings = $.extend({},defaults, options);//将一个空对象做为第一个参数return this.css({"color": settings.color,"fontSize": settings.fontSize});}//定义Beautifier的构造函数var Beautifier = function(ele, opt) {this.$element = ele,this.defaults = {"color": "red","fontSize": "12px","textDecoration":"none"},this.options = $.extend({}, this.defaults, opt)}//定义Beautifier的方法Beautifier.prototype = {beautify: function() {return this.$element.css({"color": this.options.color,"fontSize": this.options.fontSize,"textDecoration": this.options.textDecoration});}}//在插件中使用Beautifier对象$.fn.myPlugin = function(options) {//创建Beautifier的实体var beautifier = new Beautifier(this, options);//调用其方法return beautifier.beautify();}通过上面这样一改造,我们的代码变得更面向对象了,也更好维护和理解,以后要加新功能新方法,只需向对象添加新变量及方法即可,然后在插件里实例化后即可调用新添加的东西。$(function() {$("a").myPlugin({"color": "#2C9929","fontSize": "20px"});})
指定文字带下划线(我们在Beautifier对象中新加的功能,默认不带下划线,如上面的例子)的调用:
$(function() {$("a").myPlugin({"color": "#2C9929","fontSize": "20px","textDecoration": "underline"});})
到这里,你可以更好地编写复杂的插件同时很好地组织代码了。当我们回头去看上面的代码时,其实也还是有改进空间的。也就是下面介绍的关于命名空间及变量各什么的,一些杂项。
关于命名空间
不仅仅是jQuery插件的开发,我们在写任何JS代码时都应该注意的一点是不要污染全局命名空间。因为随着你代码的增多,如果有意无意在全局范围内定义一些变量的话,最后很难维护,也容易跟别人写的代码有冲突。
比如你在代码中向全局window对象添加了一个变量status用于存放状态,同时页面中引用了另一个别人写的库,也向全局添加了这样一个同名变量,最后的结果肯定不是你想要的。所以不到万不得已,一般我们不会将变量定义成全局的。
一个好的做法是始终用自调用匿名函数包裹你的代码,这样就可以完全放心,安全地将它用于任何地方了,绝对没有冲突。
用自调用匿名函数包裹你的代码
我们知道JavaScript中无法用花括号方便地创建作用域,但函数却可以形成一个作用域,域内的代码是无法被外界访问的。如果我们将自己的代码放入一个函数中,那么就不会污染全局命名空间,同时不会和别的代码冲突。
如上面我们定义了一个Beautifier全局变量,它会被附到全局的window对象上,为了防止这种事情发生,你或许会说,把所有代码放到jQuery的插件定义代码里面去啊,也就是放到$.fn.myPlugin里面。这样做倒也是种选择。但会让我们实际跟插件定义有关的代码变得臃肿,而在$.fn.myPlugin里面我们其实应该更专注于插件的调用,以及如何与jQuery互动。
所以保持原来的代码不变,我们将所有代码用自调用匿名函数包裹。
(function() {//定义Beautifier的构造函数var Beautifier = function(ele, opt) {this.$element = ele,this.defaults = {"color": "red","fontSize": "12px","textDecoration": "none"},this.options = $.extend({}, this.defaults, opt)}//定义Beautifier的方法Beautifier.prototype = {beautify: function() {return this.$element.css({"color": this.options.color,"fontSize": this.options.fontSize,"textDecoration": this.options.textDecoration});}}//在插件中使用Beautifier对象$.fn.myPlugin = function(options) {//创建Beautifier的实体var beautifier = new Beautifier(this, options);//调用其方法return beautifier.beautify();}})();这样做的好处,也就是上面所阐述的那样。另外还有一个好处就是,自调用匿名函数里面的代码会在第一时间执行,页面准备好过后,上面的代码就将插件准备好了,以方便在后面的代码中使用插件。var foo=function(){//别人的代码}//注意这里没有用分号结尾//开始我们的代码。。。(function(){//我们的代码。。alert("Hello!");})();
原因是我们用来充当自调用匿名函数的第一对括号与上面别人定义的函数相连,因为中间没有分号嘛,总之我们的代码无法正常解析了,所以报错。
所以好的做法是我们在代码开头加一个分号,这在任何时候都是一个好的习惯。
var foo=function(){//别人的代码}//注意这里没有用分号结尾//开始我们的代码。。。;(function(){//我们的代码。。alert("Hello!");})();;(function($,window,document,undefined){//我们的代码。。//blah blah blah...})(jQuery,window,document);;(function($, window, document,undefined) {//定义Beautifier的构造函数var Beautifier = function(ele, opt) {this.$element = ele,this.defaults = {"color": "red","fontSize": "12px","textDecoration": "none"},this.options = $.extend({}, this.defaults, opt)}//定义Beautifier的方法Beautifier.prototype = {beautify: function() {return this.$element.css({"color": this.options.color,"fontSize": this.options.fontSize,"textDecoration": this.options.textDecoration});}}//在插件中使用Beautifier对象$.fn.myPlugin = function(options) {//创建Beautifier的实体var beautifier = new Beautifier(this, options);//调用其方法return beautifier.beautify();}})(jQuery, window, document);一个安全,结构良好,组织有序的插件编写完成。var name = "Wayou";document.getElementById(‘example").innerHTML = "< a href="http: //wayouliu.duapp.com/">"+name+"</a>"; //href=".." HTML中保持双引号,JavaScript中保持单引号一方面,HTML代码中本来就使用的是双引号,另一方面,在JavaScript中引号中还需要引号的时候,要求我们单双引号间隔着写才是合法的语句,除非你使用转意符那也是可以的。再者,坚持这样的统一可以保持代码风格的一致,不会出现这里字符串用双引号包着,另外的地方就在用单引号。
{"name": "sliphover","title": "SlipHover","description": "Apply direction aware 2D/3D hover effect to images","keywords": ["direction-aware","animation","effect","hover","image","overlay","gallery"],"version": "1.1.1","author": {"name": "Wayou","email": "liuwayong@gmail.com","url": "https://github.com/Wayou"},"maintainers": [{"name": "Wayou","email": "liuwayong@gmail.com","url": "https://github.com/Wayou"}],"licenses": [{"type": "MIT","url": "https://github.com/jquery/jquery-color/blob/2.1.2/MIT-LICENSE.txt"}],"bugs": "https://github.com/Wayou/sliphover/issues","homepage": "http://wayou.github.io/SlipHover/","docs": "http://wayou.github.io/SlipHover/","demo":"http://wayou.github.io/SlipHover/","download": "https://github.com/Wayou/SlipHover/zipball/master","dependencies": {"jquery": ">=1.5"}}•然后就可以在插件的根目录执行现行git代码来发布插件了。其中0.1.0是版本号,以后每次你的插件有新版本发布只需更新上面命令中的版本,创建新的tag,这样jQuery插件中心就会自动获取到新版本信息了$ git tag 0.1.0$ git push origin --tagsGitHub Service Hook

2进入设置页面后点击"Webhooks & Services "

3然后点击右边主页面上的"Configure services" 按钮

4这时出现一个很长的列表,向下找到jQuery Plugins 点击

5点击选中框后点击"更新设置"按钮

到此就设置完成了。