1.概述
jquery插件开发的主要方法有三种:
1、通过$.extend()来扩展jQuery,即在jQuery命名空间下扩展属性,直接在$对象下调用,不需要再dom下调用,也无法在dom元素下调用:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div id="text">测试</div> </body> <script src="jquery-1.8.3.min.js"></script> <script type="text/javascript"> //jQuey插件开发方法1,在jQuery命名空间下新增属性 $.extend({ sayHello: function(name){ alert(name); } }); $.sayHello('gaoxiong'); //下面两者都相等,说明 $.fn = $.prototype console.log($.fn); console.log($.prototype); //下面说明了通过 $.extend来扩展jQuery的方法,并不是扩展jquery的原型对象 console.log($.fn.sayHello);//undefined $('#test').sayHello('gaoxiong'); //报错 </script> </html>
用途:该方法适合用来定义一些辅助方法,类似与$.ajax()等非操作dom元素的方法,为什么时辅助方法?因为现在jquery被利用的主要目的就是操作dom。但这种方式无法利用jQuery强大的选择器带来的便利,要处理DOM元素以及将插件更好地运用于所选择的元素身上,还是需要使用第二种开发方式。
2、$.fn.extend方法扩展 $.prototype
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <h1 id="h1">测试</h1> <h1>测试</h1> <h1>测试</h1> <h1>测试</h1> <h1>测试</h1> </body> <script src="lib/jquery-1.8.3.min.js"></script> <script type="text/javascript"> //jQuery插件方法二:$.fn.extend(),顾名思义,该方法是在jQuery的原型对象上新增一个方法 $.fn.extend({ returnThis: function(){ return this; } }); //可以得出,上面的this 是一个集合(类似于数组),集合中包含了所有匹配的元素(这些元素为原生JS dom元素) console.log($('#h1').returnThis()); console.log($('h1').returnThis()); //将会打印一个原生dom console.log($('h1').returnThis()[0]) //综述:在自定义插件内部中的 this 可以理解为 匹配的元素的集合(jQuery的包装对象),这个集合的原型指向$.fn //自定义一个设置字体颜色插件 $.fn.extend({ setcolor: function(colorName){ this.css('color', colorName); } }); //所有h1标签变为红色 $('h1').setcolor('red'); </script> </html>
3、关于插件内this的指向
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <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> </body> <script src="lib/jquery-1.8.3.min.js"></script> <script type="text/javascript"> //上一节,我们已经知道this 指代jQuery选择器返回的集合(包装对象) //$.each()方法可以处理合集中的每个元素,但在each方法内部,this指的是普通的DOM元素,如果调用jQuery的方法那就需要用$来重新包装一下 //案例,我希望在每个a标签后面显示url地址 $.fn.extend({ showUrl: function(){ this.each(function(){ console.log(this);//原生dom元素 $(this).append($(this).attr('href')); }) } }); $('a').showUrl(); //使用jQuery命名空间时, this的指向为一个函数(包装dom为jQuery包装对象) $.extend({ consoleThis: function(){ console.log(this); } }) $.consoleThis(); </script> </html>
4、支持链式调用
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <h1>测试</h1> <h1>测试</h1> <h1>测试</h1> <h2>测试</h2> <h2>测试</h2> <h2>测试</h2> </body> <script src="lib/jquery-1.8.3.min.js"></script> <script type="text/javascript"> //jQuery中一个非常简便的方法是支持链式调用 $.fn.extend({ setColor: function(colorName){ //如下的这种写法为便捷写法 return this.each(function(){ $(this).css('color', colorName) }) } }); $('h1').setColor('red').css('background', 'blue'); //未设置链式调用(未在插件中返回this) $.fn.extend({ setFontSize: function(size){ this.css('font-size', size); } }) //因为未在插件中返回this,那么$('h2').setFontSize('50px')为一个undefined,如下会报错 $('h2').setFontSize('50px').css('background', 'yellow'); </script> </html>
5、设置默认参数
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <h1>测试</h1> <h1>测试</h1> <h2>测试</h2> <h2>测试</h2> </body> <script src='lib/jquery-1.8.3.min.js'></script> <script type="text/javascript"> //设置默认参数,先学会$.extend(obj1, obj2) var DEFAULTS = { age: 25, name: 'gaoxiong' }; var options = { age: 24, name: 'jiaojiao' }; var settings = $.extend(DEFAULTS, options); console.log(settings);//age=>24, name=>jiaojiao console.log(options);//不变 console.log(DEFAULTS);//与setting一样 $.fn.extend({ setColor: function(options){ var defaults = { fontSize: '50px', color: 'blue' }; var settings = $.extend(defaults, options); return this.css(settings); } }); $('h1').setColor(); $('h2').setColor({ color: 'red', fontSize: '12px' }) </script> </html>
6、保护默认参数
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <h1>测试</h1> <h1>测试</h1> <h2>测试</h2> <h2>测试</h2> </body> <script src='lib/jquery-1.8.3.min.js'></script> <script type="text/javascript"> //保护好默认参数,在一个插件中,默认参数可能被使用多次,上述方法会修改默认配置参数 //$.extend({}, defaults, options)避免了默认配置的修改 var defaults = { age: 25, name: 'gaoxiong' }; var options = { age: 25, name: 'jiaojiao' }; var setiings = $.extend({}, defaults, options); console.log(setiings); // name => jiaojiao console.log(defaults); // name => gaoxiong ,并没有修改defaults </script> </html>
7、面向对象的插件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <p>测试</p> <p>测试</p> <p>测试</p> <div>测试</div> <div>测试</div> <div>测试</div> </body> <script src="lib/jquery-1.8.3.min.js"></script> <script type="text/javascript"> //面向对象的插件开发,当项目变大或者版本迭代时,方便维护,结构清晰化 //定义一个类 var Beautifier = function(element, options){ this.$element = element; this.defualts = { color: 'red', fontSize: '20px', textDecoration: 'none' }; this.options = $.extend({}, this.defualts, options); }; //添加原型方法 Beautifier.prototype = { beautify: function(){ return this.$element.css({ color: this.options.color, fontSize: this.options.fontSize, textDecoration: this.options.textDecoration }) } }; //将方法挂载到$.fn $.fn.extend({ beautify: function(options){ return this.each(function(){ new Beautifier($(this), options).beautify(); }) } }) //使用 $('p').beautify().css('background', 'blue'); $('div').beautify({ color: 'green', fontSize: '100px', textDecoration: 'decoration' }) </script> </html>
8、命名空间变量污染
不仅仅是jQuery插件的开发,我们在写任何JS代码时都应该注意的一点是不要污染全局命名空间,常用的方法是 用自调用匿名函数包裹你的代码。
匿名函数避免命名空间污染的原理:JavaScript中无法用花括号方便地创建作用域,但函数却可以形成一个作用域,域内的代码是无法被外界访问的。如果我们将自己的代码放入一个函数中,那么就不会污染全局命名空间,同时不会和别的代码冲突。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <p>测试</p> <p>测试</p> <p>测试</p> <div>测试</div> <div>测试</div> <div>测试</div> </body> <script src="lib/jquery-1.8.3.min.js"></script> <script type="text/javascript"> (function(){ var Beautifier = function(element, options){ this.$element = element; this.defualts = { color: 'red', fontSize: '20px', textDecoration: 'none' }; this.options = $.extend({}, this.defualts, options); }; Beautifier.prototype = { beautify: function(){ return this.$element.css({ color: this.options.color, fontSize: this.options.fontSize, textDecoration: this.options.textDecoration }) } }; $.fn.extend({ beautify: function(options){ return this.each(function(){ new Beautifier($(this), options).beautify(); }) } }) })(); $('p').beautify().css('background', 'blue'); $('div').beautify({ color: 'green', fontSize: '100px', textDecoration: 'decoration' }) </script> </html>
9、将系统变量以参数形式传递到插件内部
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> </body> <script src="lib/jquery-1.8.3.min.js"></script> <script type="text/javascript"> //经过我前面8小节的复习,开发插件好像已经完美了,实际上还有一些细节需要处理 //1. 将这段代码放到页面后,前面别人写的代码没有用分号结尾 //2. 前面的代码将window, undefined等这些系统变量或者关键字修改掉了 //第一种情况 //别人的代码,这里没有使用分号结尾 var foo = function(){ } //我写的代码 ;(function(){ alert('Hello!'); })(); //原因:充当自调用匿名函数的第一对括号,与上面别人定义的函数相连,导致组成希望的两个语句 组成了一个语句,出现语法错误 //解决方法:在匿名函数包裹的圆括号前加分号 //第二种情况:将系统变量以参数形式传递到插件内部。这样做之后: //1. window等系统变量在插件内部就有了一个局部的引用,可以提高访问速度,会有些许性能的提升 //2. 而至于这个undefined,为了得到没有被修改的undefined,我们并没有传递这个参数,但却在接收时接收了它,因为实际并没有传,所以‘undefined'那个位置接收到的就是真实的'undefined'了。 //其实上述两个解决办法,在jQuery这个库中本来就有使用到 //正式版本:一个安全,结构良好,组织有序的插件编写完成。 ;(function($, window, document, undefined){ alert('Hello!'); })(jQuery, window, document); </script> </html>
10、代码编写规范
1、变量定义
- 做法:把将要使用的变量名用一个var关键字一并定义在代码开头,变量名间用逗号隔开
- 原因:
- 一是便于理解,了解下面的代码会用到哪些变量,同时代码显得整洁且有规律,也方便管理,变量定义与逻辑代码分开。
- 二是因为JavaScript中所有变量及函数名会自动提升,也称之为JavaScript的Hoist特性,即使你将变量的定义穿插在逻辑代码中,在代码解析运行期间,这些变量的声明还是被提升到了当前作用域最顶端的,所以我们将变量定义在一个作用域的开头是更符合逻辑的一种做法。
2、变量及函数命名
- 做法:一般使用驼峰命名法(CamelCase),即首个单词的首字母小写,后面单词首字母大写,比如 showButton。
3、常量命名
- 做法:对于常量,所有字母采用大写,多个单词用下划线隔开,比如WIDTH=100,BRUSH_COLOR='#00ff00'。
4、当变量为jQuery类型时
- 当变量是jQuery类型时,建议以$开头,开始会不习惯,但经常用了之后会感觉很方便,因为可以很方便地将它与普通变量区别开来,一看到以$开头我们就知道它是jQuery类型可以直接在其身上调用jQuery相关的方法,比如var $element=$('a'); 之后就可以在后面的代码中很方便地使用它,并且与其他变量容易区分开来。
5、引号的使用
- 引号的使用:一般HTML代码里面使用双引号,而在JavaScript中多用单引号。