jQuery插件的开发包括两种:
一种是类级别的插件开发$.extend,即给jQuery添加新的全局函数,相当于给jQuery类本身添加方法,比如:$.ajax, $.getJSON等。jQuery的全局函数就是属于jQuery命名空间的函数,另一种是对象级别的插件开发$.fn.extend,即给jQuery对象添加方法。比如:$.css()等。为了保持jQuery的完整性,一般趋向于使用$.fn.extend进行插件开发而尽量少使用$.extend。
一、$.extend(src),
$.extend方法是将src合并到jQuery全局对象中去,相当于静态方法。
开发扩展其方法时使用$.extend方法,即jQuery.extend(object);
$.extend({ add: function(a, b) { return (a + b) }, minus: function(a, b) { return (a - b) }, print: function(a, b) { console.log(a + ',' + b); } });
页面中调用:
var i = $.add(3,2); var j = $.minus(3,2);
var k = $.print(3,2)
二、$.fn.extend,
$.fn.extend对象级别则可以理解为基于对象的拓展,如$("#table").changeColor(...); 这里这个changeColor呢,就是基于对象的拓展了。
开发扩展其方法时使用$.fn.extend方法,即jQuery.fn.extend(object);
$.fn.extend({ check: function() { return this.each(function() { this.checked = true; }) }, uncheck: function() { return this.each(function() { this.checked = false; }) }, click: function() { return this.each(function(index, value) { console.log($.type(this)); console.log(index); }) } });
页面中调用:
$("input[type=checkbox]").check() $("input[type=radio]").uncheck() $("input[type=checkbox]:eq(0)").click()
来看一个综合例子
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <title>插件开发</title> <script src="http://apps.bdimg.com/libs/jquery/1.10.1/jquery.min.js"></script> </head> <body> <p></p> <p></p> <p></p> <p></p> <p></p> <script> (function($){ $.fn.myStyle=function(options){ var defaults={ color:'black', fontSize:'12px', padding:0, margin:0, text:"This is a text!", font:"microsoft yahei", } var obj=$.extend(defaults,options); return this.each(function(index, el) { var me=$(this) me.html(obj.text); me.css({ color:obj.color, fontSize:obj.fontSize, padding:obj.padding, margin:obj.margin, fontFamily:obj.font }) }); } })(jQuery) //页面调用 $("p").myStyle({ color:"red", fontSize:'18px', font:'simsun', }) </script> </body> </html>
三、插件方法
在任何情况下,一个单独的插件不应该在jQuery.fnjQuery.fn对象里有多个命名空间。
(function($) { $.fn.tooltip = function(options) { // this }; $.fn.tooltipShow = function() { // is }; $.fn.tooltipHide = function() { // bad }; $.fn.tooltipUpdate = function(content) { // !!! }; })(jQuery);
这是不被鼓励的,因为它$.fn使$.fn命名空间混乱。 为了解决这个问题,你应该收集对象文本中的所有插件的方法,通过传递该方法的字符串名称给插件以调用它们。参看下面这个代码:
(function($) { var methods = { init: function(options) { // this }, show: function() { // is }, hide: function() { // good }, 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); //调用init方法 $('div').tooltip(); //调用init方法 $('div').tooltip({ foo: 'bar' }); // 调用hide方法 $('div').tooltip('hide'); //调用Update方法 $('div').tooltip('update', 'This is the new tooltip content!');
这种方法推荐使用;
来看一个综合例子:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title></title> <style> .box{width: 300px;height: 300px;background: red;} </style> <script src="http://apps.bdimg.com/libs/jquery/1.10.1/jquery.min.js"></script> </head> <body> <div class="box">11</div> <script> (function($){ var methods={ init:function(options){ var defaults = { foreground: 'red', background: 'yellow', text:'This is a paragraph!' }; var obj=$.extend(defaults,options); $(this).each(function(){ $(this).html(obj.text); $(this).css({ color:obj.foreground, background:obj.background, }); }) }, alertClick:function(){ $(this).click(function() { alert($(this).html()); }); } } $.fn.myPlugin=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.myPlugin'); } } })(jQuery) $('.box').myPlugin('init') $('.box').myPlugin('alertClick') </script> </body> </html>
四、面向对象的插件开发;
面向对象编程的概念和重要性不再阐述。对于插件开发来说,为什么要使用面向对象的思维。假设你不这样做,当你需要一个方法的时候就去定义一个function,需要另外一个方法的时候,再去定义一个function,毫无规则地定义一些散落在代码各处的变量和方法,结构不够清晰,维护起来也不方便。
假设使用面向对象的思想设计插件,将需要的重要变量定义到对象的属性上,函数变成对象的方法,一来方便管理,二来不会影响外部命名空间,因为所有这些变量名还有方法名都是在对象内部。
来看下面这面向对象开发的插件:
(function($) { //定义Beautifier的构造函数 var Beautifier = function(ele, options) { this.$ele = ele; this.opt = options; this.defaults = { 'color': 'red', 'fontSize': '12px', 'textDecoration': 'none' }, this.obj = $.extend({}, this.defaults, this.opt); } //定义Beautifier的方法 Beautifier.prototype.beautify = function() { return this.$ele.css({ color: this.obj.color, fontSize: this.obj.fontSize, textDecoration: this.obj.textDecoration, }) } //在插件中使用Beautifier对象 $.fn.beautify = function(options) { //创建Beautifier的实例 var beautifier = new Beautifier(this, options); //调用其方法 return beautifier.beautify() } })(jQuery)
经过上面一番改造,我们的插件变得面向对象了,更好维护和理解。以后要加新功能新方法,只需向对象添加新变量及方法即可,然后在插件里实例化后即可调用新添加的东西。插件的调用还是一样的,我们对代码的改动并不影响插件其他地方,只是将代码的组织结构改动了而以。
// 插件调用 $(".box").beautify();
将系统变量以变量形式传递到插件内部。
var foo=function(){ //别人的代码 }//注意这里没有用分号结尾 //开始我们的代码。。。 (function(){ //我们的代码。。 alert('Hello!'); })();
本来别人的代码也正常工作,但是最后定义的那个函数没有用分号结尾,然后当页面中引入我们的插件时,报错了,代码无法正常执行。原因是我们用来充当自调用匿名函数的第一对括号与上面别人定义的函数相连,因为中间没有分号嘛,我们的代码无法正常解析了,所以报错。所以好的做法是我们在代码开头加一个分号,这在任何时候都是一个好的习惯。
var foo=function(){ //别人的代码 }//注意这里没有用分号结尾 //开始我们的代码。。。 ;(function(){ //我们的代码。。 alert('Hello!'); })();
同时,将系统变量以参数形式传递到插件内部也是个不错的实践。当我们这样做之后,window等系统变量在插件内部就有了一个局部的引用,可以提高访问速度,会有些许性能的提升。
;(function($,window,document,undefined){ //我们的代码。。 //blah blah blah... })(jQuery,window,document);
而至于这个undefined,就非常有意思了,为了得到没有被修改的undefined,我们并没有传递这个参数,但却在接收时接收了它,因为实际并没有传,所以‘undefined’那个位置接收到的就是真实的'undefined'了。这是值得细细体会的技术和思维方式,当然不是我发明的,都是从前人的经验中学习到的。所以最后我们的插件成了这样:
;(function($, window, document,undefined) { //定义Beautifier的构造函数 var Beautifier = function(ele, options) { this.$ele = ele; this.opt = options; this.defaults = { 'color': 'red', 'fontSize': '12px', 'textDecoration': 'none' }, this.obj = $.extend({}, this.defaults, this.opt); } //定义Beautifier的方法 Beautifier.prototype.beautify = function() { return this.$ele.css({ color: this.obj.color, fontSize: this.obj.fontSize, textDecoration: this.obj.textDecoration, }) } //在插件中使用Beautifier对象 $.fn.beautify = function(options) { //创建Beautifier的实例 var beautifier = new Beautifier(this, options); //调用其方法 return beautifier.beautify() } })(jQuery, window, document);
一个安全,结构良好,组织有序的插件编写完成。