jQuery本身功能强大,又提供了超强的可扩展性,便于人们为其开发各种插件,本文便讲解如何开发jQuery自定义插件。有幸遇到下面这篇前端大牛的神作,遂本文仅参照此文略作修改,再次感谢这位前端大牛的神作。
文档来源:http://www.cnblogs.com/Wayou/p/jquery_plugin_tutorial.html
1、通过$.extend()来扩展jQuery,如$.ajax()即采用该方式开发
2、通过$.fn 向jQuery添加新的方法,如$(“div”).first()即采用该方式开发
3、通过$.widget()应用jQuery UI的部件工厂方式创建,该方法可以开发更高级jQuery插件,在本文中不作讨论
通过$.extend()添加的方法,调用时直接通过$.方法名()来调用。因其本质上是在jQuery本身上添加的一个静态方法。
<script type="text/javascript" src="jquery-1.7.1.min.js">script>
<script type="text/javascript">
$.extend({
//将要添加的插件
scroll:function(obj){
console.log((obj?obj:"nothing")+" will scroll");
}
})
//调用插件
$.scroll();//nothing will scroll
$.scroll("div"); //div will scroll
//本例通过$.extend()向jQuery添加了一个scroll函数,然后通过$.scroll()直接调用。
//这就完成了一个简单的jQuery插件开发的工作
script>
这种方式用来定义一些辅助方法是比较方便的,如jQuery中已有的$.ajax()、$.trim()等等。
但这种方式无法利用jQuery强大的选择器带来的便利,要处理DOM元素以及将插件更好地运用于所选择的元素身上,还是需要使用第二种开发方式。你所见到或使用的插件也大多是通过此种方式开发。
在讲解第二种开发插件的方法前,先准备一段用于jQuery操作的html代码如下:
<nav>
<ul id="nav">
<li><a href="http://www.baidu.com" title="首页" target="_blank">首页a>li>
<li><a href="http://www.sina.com" title="新闻" target="_blank">新闻a>li>
<li><a href="http://www.qq.com" title="评论" target="_blank">评论a>li>
ul>
nav>
基本格式都是往$.fn上面添加一个方法,名字是将要开发的插件名(如下代码中的change)。然后插件代码在这个方法里面编写,代码如下:
在插件函数内部,this指代的是调用该插件的jQuery选择器选中的元素集合,一般是一个jQuery类型的集合。因此插件函数内部的this已经是一个jQuery类型了,不需要再进行$(this)这样的包装操作,而是可以直接在this身上调用jQuery的方法了。
<script type="text/javascript">
$.fn.change = function() {
//your code goes here
//在插件函数内部,this指代的是调用该插件的jQuery选择器选中的元素集合,一般是一个jQuery类型的集合
//因此,此处的this已经是一个jQuery类型了,不需要再进行$(this)这样的包装操作,而是可以直接在this身上调用jQuery的方法了。
//例如:$('li').change,则在change插件内部this===$('li')
//因此可以使用this.css(),相当于$('li').css()
}
script>
第一步:对一个集合进行处理
$.fn.change = function() {
//插件方法内部的代码
//此处的this指代的是jQuery选择器选中的jQuery类型的元素集合
this.css("border","1px solid red");
}
插件的调用如下,其中$(“#nav”).find(‘li’).change() 则是处理页面上#nav内的所有li标签的集合
<script type="text/javascript">
$(function(){
$("#nav").find('li').change();
})
script>
再进一步,针对每个具体的元素进行相应操作
插件内部的this指代jQuery选择器返回的集合,那么通过调用jQuery的\$().each()方法就可以处理集合中的每个具体元素
但此刻要注意的是,在each方法内部,this指代的是普通的DOM元素了,而不是jQuery类型,如果需要调用jQuery的方法那就需要用$来重新包装一下。
$.fn.change = function() {
//3.2 对一个集合进行处理
this.css("border","1px solid red");
//3.3 针对每个具体的元素进行相应操作
this.each(function(){
//对每个具体元素进行操作————要在每个链接显示链接的真实地址,
//首先通过each遍历所有a标签,然后获取href属性的值再加到链接文本后面。
//在$().each方法内部,this指代的是普通的DOM元素了,而不是jQuery类型,
//如果需要调用jQuery的方法那就需要用$来重新包装一下。
$(this).append(' '+$(this).find("a").attr('href'));
})
}
插件的调用方式同上,效果如下图, (margin-bottom:5px未在代码中粘贴出来)
再进一步,支持链式调用
jQuery一个非常优雅的特性是支持链式调用,选择好DOM元素后可以不断地调用其他方法
为了让本插件支持链式调用特性,只需return一下this.each()即可
$.fn.change = function() {
//3.2 对一个集合进行处理
this.css("border","1px solid red");
//3.3 针对每个具体的元素进行相应操作
//3.4 支持链式调用
return this.each(function(){
$(this).append(' '+$(this).find("a").attr('href'));
})
}
插件的调用如下:
<script type="text/javascript">
$(function(){
//支持链式调用
$("#nav").find('li').change()
.first().find('a').text("百度");
})
})
script>
一个强劲的插件是可以让使用者随意定制的,这要求我们提供在编写插件时就要考虑得全面些,尽量提供合适的参数。
如想让插件的使用者自己定义边框显示什么颜色,只需使用者在调用插件时传入一个参数即可,同时在插件的代码里面接收。同时为了灵活使用插件,使用者可以不传递参数,插件里面会给出参数的默认值。
在处理插件参数的接收上,通常使用jQuery的$.extend()方法,其用法如下:
a、当给extend方法传递单个对象时,这个对象会合并到jQuery身上,就可以在jQuery身上调用新合并对象里包含的方法了,如第一种方式开发插件的例子。
b、当给extend方法传递一个以上的参数时,会将所有参数对象合并到第一个参数里。同时,如果对象中有同名属性时,合并的时候后面的会覆盖前面的。
利用b用法这一点,可以在插件里定义一个保存插件参数默认值的对象,同时将接收来的参数对象合并到默认对象上,最后就实现了用户指定了值的参数使用指定的值,未指定的参数使用插件默认值。
//有参插件
$.fn.change = function(options) {
//默认参数
var defaults = {
'border':'1px solid red',
'fontSize':'14px',
"marginBottom":"5px"
};
//合并参数
var settings = $.extend(defaults,options);
return this.each(function(){
$(this).css({
"border":settings.border,
"fontSize":settings.fontSize,
"margin-bottom":settings.marginBottom
});
$(this).append(' ' + $(this).find("a").attr('href'));
})
}
插件调用如下:
<script type="text/javascript">
$(function(){
//自定义参数,只指定边框颜色,其他取默认值
//$("#nav").find('li').change({
// "border":"1px solid blue"
//})
//自定义参数,指定边框颜色和字体大小,其他取默认值
$("#nav").find('li').change({
"border":"1px solid blue",
"fontSize":"16px"
})
})
script>
再进一步,保护默认参数
上面代码调用extend时会将defaults的值改变,如下图。这样不好,因为它作为插件应有的一些东西应该维持原样。
另外就是如果你在后续代码中还要使用这些默认值的话,当你再次访问它时它已经被用户传进来的参数更改了。
一个好的做法是将一个新的空对象做为$.extend的第一个参数,defaults和用户传递的参数对象紧随其后,这样做的好处是所有值被合并到这个空对象上,保护了插件里面的默认值。
//有参插件
$.fn.change = function(options) {
//默认参数
var defaults = {
'border':'1px solid red',
'fontSize':'14px',
"marginBottom":"5px"
};
//合并参数
//3.5 将一个空对象做为第一个参数来合并参数
var settings = $.extend({},defaults,options);
return this.each(function(){
$(this).css({
"border":settings.border,
"fontSize":settings.fontSize,
"margin-bottom":settings.marginBottom
});
$(this).append(' ' + $(this).find("a").attr('href'));
})
}
考虑到文章篇幅,本文暂到这里结束,第二部分请移步:如何开发jQuery自定义插件二