要说jQuery 最成功的地方,我认为是它的可扩展性吸引了众多开发者为其开发插件,从而建立起了一个生态系统。这好比大公司们争相做平台一样,得平台者得天下。苹果,微软,谷歌等巨头,都有各自的平台及生态圈。
学会使用jQuery并不难,因为它简单易学,并且相信你接触jQuery后肯定也使用或熟悉了不少其插件。如果要将能力上升一个台阶,那么如何编写一个自己的插件呢?
jQuery插件开发方式主要有三种:
比如我们将页面上所有链接颜色转成红色,则可以这样写这个插件:
$.fn.myPlugin = function() {
//在这里面,this指的是用jQuery选中的元素
//example :$('a'),则this=$('a')
this.css('color', 'red');
}
支持链式调用
$.fn.myPlugin = function() {
//在这里面,this指的是用jQuery选中的元素
//example :$('a'),则this=$('a')
return this.css('color', 'red');
}
在插件名字定义的这个函数内部,this指代的是我们在调用该插件时,用jQuery选择器选中的元素,一般是一个jQuery类型的集合。比如$('a')返回的是页面上所有a标签的集合,且这个集合已经是jQuery包装类型了,也就是说,在对其进行操作的时候可以直接调用jQuery的其他方法而不需要再用美元符号来包装一下。
所以在上面插件代码中,我们在this身上调用jQuery的css()方法,也就相当于在调用 $('a').css()。
我们假设有这样一个页面
<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>
JS
$(function(){
$('a').myPlugin();
})
运行这个代码就可以使得相应的a标签变色
到此,你已经可以编写功能简单的jQuery插件了。但这里还有个问题是如果我这个函数要接收参数应该怎么写呢?
一个强劲的插件是可以让使用者随意定制的,这要求我们提供在编写插件时就要考虑得全面些,尽量提供合适的参数。
比如现在我们不想让链接只变成红色,我们让插件的使用者自己定义显示什么颜色,要做到这一点很方便,只需要使用者在调用的时候传入一个参数即可。同时我们在插件的代码里面接收。另一方面,为了灵活,使用者可以不传递参数,插件里面会给出参数的默认值。
在处理插件参数的接收上,通常使用jQuery的extend方法
同时指定颜色与字体大小:
$.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',
'fontSize': '20px'
});
运行结果
现在,我们调用的时候指定颜色,字体大小未指定,会运用插件里的默认值12px。
$('a').myPlugin({
'color': '#2C9929'
});
到此,插件可以接收和处理参数后,就可以编写出更健壮而灵活的插件了。若要编写一个复杂的插件,代码量会很大,如何组织代码就成了一个需要面临的问题,没有一个好的方式来组织这些代码,整体感觉会杂乱无章,同时也不好维护,所以将插件的所有方法属性包装到一个对象上,用面向对象的思维来进行开发,无疑会使工作轻松很多。
为什么要有面向对象的思维,因为如果不这样,你可能需要一个方法的时候就去定义一个function,当需要另外一个方法的时候,再去随便定义一个function,同样,需要一个变量的时候,毫无规则地定义一些散落在代码各处的变量。
还是老问题,不方便维护,也不够清晰。
所以我们新建一个对象命名为Beautifier,然后我们在插件里使用这个对象来编码。
//定义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对象上,为了防止这种事情发生,我们保持原来的代码不变,将所有代码用自调用匿名函数包裹.
(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();
}
})();
这样做的好处,也就是上面所阐述的那样。另外还有一个好处就是,自调用匿名函数里面的代码会在第一时间执行,页面准备好过后,上面的代码就将插件准备好了,以方便在后面的代码中使用插件。
目前为止似乎接近完美了。如果再考虑到其他一些因素,比如我们将这段代码放到页面后,前面别人写的代码没有用分号结尾,或者前面的代码将window, undefined等这些系统变量或者关键字修改掉了,正好我们又在自己的代码里面进行了使用,那结果也是不可预测的,这不是我们想要的。
所以好的做法是我们在代码开头加一个分号,这在任何时候都是一个好的习惯。
var foo=function(){
//别人的代码
}//注意这里没有用分号结尾
//开始我们的代码。。。
;(function(){
//我们的代码。。
alert('Hello!');
})();
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。