在网上有各种各样的jQuery插件,一个jQuery插件可以实现某项功能,完成某种炫酷的效果。那么,一个jQuery插件是如何开发出来的呢?使用jQuery来编写jQuery插件有2种形式:全局jQuery插件和基于包装集的jQuery插件。
全局jQuery插件
我们直接通过$.方法名称
就可以定义一个全局的jQuery插件。例如:
$.say = function(name){ alert("hello" + name); }
调用全局插件的方法也非常简单:
$(function(){ $.say("Tom"); })
在编写一个jQuery插件的时候,我们还需要考虑以下一些问题:
- 1、一般jQuery插件都需要通过一个独立的js文件来存储,我们应该如何确定插件命名的规则?
- 2、如果将来
$
这个符号被jQuery.noConflict
之后,如何保证插件还能继续使用? - 3、如何为插件设置参数?
对于第一个问题,我们在为jQuery插件进行命名的时候,通常都遵循jquery.命名空间.js
的命名规则。例如,如果是一个幻灯片插件,我们可以命名为:jquery.mySlider.js。
对于第二个问题,我们可以将$
改为jQuery,但是这种方式会增加我们的插件开发的工作量。最好的办法是将整个插件都写在一个闭包中,例如:
(function($){ //插件在此定义 })(jQuery);
在上面的代码中,$
不再是jquery中的$
,而是闭包中的$
,而闭包中的$
又是jQuery对象。
插件编写的第三个问题是参数的问题,假设我们有一个插件,它的参数非常多,其中,只有第一个和最后一个参数的必须的参数,其它参数都是可选的参数,我们需要向下面这样来调用这个插件:
// 插件的定义,有8个参数 $.myPlugins = function(p1,p2,p3,p4,p5,p6,p7,p8){ //...... } // 插件的调用 $(function(){ $.myPlugins("value1",null,null,null,null,null,null,null,"value2"); })
这种调用插件的方法会让使用者崩溃。我们注意观察jQuery中提供的一些方法,例如事件处理中的bind()
方法:
bind(type,[data],fn)
这个方法的第二个参数data
是一个可选参数。我们知道,JavaScript是不支持方法的重载的,那么jQuery是如何实现同一个方法的多种参数的调用的呢?
答案是在jQuery中有一个非常重要的方法:extend()
。extend()
方法会用第二个参数对象来覆盖第一个参数对象,如果没有的就不进行覆盖,而第二个参数始终不会发生变化。例如:
var person1 = {name:"tom",age:29,email:"123@qq.com"} var person2 = {name:"jarry",age:30} $.extend(person1,person2); console.info(person1.name+","+person1.age+","+person1.email); console.info(person2.name+","+person2.age);
执行上面的代码,查看控制台的输出,可以看到下面的输出结果:
jarry,30,123@qq.com jarry,30
person1的name
和age
属性会被person2的同名属性覆盖,person2的属性保持不变。
如果希望获取被覆盖后的对象,extend()
方法提供了第3个参数,来保存被覆盖后的对象。
$.extend(p,person1,person2); console.info(person1.name+","+person1.age+","+person1.email); console.info(person2.name+","+person2.age); console.info(p.name+","+p.age+","+p.email);
在jQuery插件的编写中,通常是通过extend()
方法来完成自定义参数的设置。以前面的myPlugins插件为例,我们可以将它修改为:
$.myPlugins = function(p1,options,p2){ //在代码中通过extend方法来完成覆盖 var settings = $.extend({ a2:"value1", a3:"value2", a4:"value3", a5:"value4", a6:"value5", a7:"value6", } ,options || {}) }
extend()
方法中的第一个参数是一个json对象,在这个json对象中为参数a2-a7设置了一个默认值,然后将第二个参数设置为options
,这是一个用户自定义的参数选项,如果用户没有提供自定义的参数,那么就是用插件的默认参数,否则用户定义的参数会覆盖插件的默认参数。例如:
$(function(){ $.myPlugins("abc",{ a2:"hello" },"xyz") })
上面调用插件的方法会将插件的a2参数覆盖为“hello”。
基于包装集的jQuery插件
基于包装集的jQuery插件的形式为:$.fn.myplugins
。这是我们编写jQuery插件最常用的一种方式。
$.fn
是什么意思呢?我们可以查看jQuery的源代码:
jQuery.fn = jQuery.prototype = { init: function( selector, context ) { //...... } };
原来$.fn
是jQuery.prototype
的另外一种写法。prototype
是JavaScript的。jQuery不建议直接在原型上扩展方法,所以提供了一个$.fn
给开发者用于插件的编写。
例如编写一个修改文字颜色的jQuery插件。
$.fn.setColor = function(){ this.css("color","#f00"); //基于包装集的函数一定要能够支持链式编程结构 return this; }
注意,在匿名函数的内部,this
对象引用的是整个包装集,不需要在使用$(this)
来重新包装。
另外,基于包装集的函数一定要能够支持链式编程结构,所以一定要返回this
对象。
一个简单的jQuery幻灯片插件的例子
下面我们将以一个最简单的jQuery幻灯片插件的制作为例子。在这个例子中使用的是基于包装集的jQuery插件。先来看一下这个幻灯片的HTML结构:
<div class="slider-warp"> <div> <ul> <li> <img src="images/1.jpg" /> </li> <li> <img src="images/2.jpg" /> </li> <li> <img src="images/3.jpg" /> </li> </ul> </div> <div class="mySlider-arrow"><span class="prev"></span><span class="next"></span></div> </div>
在上面的HTML结构中,幻灯片使用一个<div>
作为包裹元素,里面使用无序列表作为幻灯片的元素。最后的.mySlider-arrow
是前后导航的箭头按钮。
为这个幻灯片添加下面的一些基本的CSS样式。
.slider-warp{ width: 500px; height: 281px; position: relative; overflow: hidden; } .slider-warp ul{ padding: 0px; margin: 0px; position: absolute; } .slider-warp li{ list-style: none; } .slider-warp li img{ display: block; width: 100%; margin: 0px; padding: 0px; } .mySlider-nav{ position: absolute; z-index: 2; bottom: 2px; text-align: center; width: 100%; margin: 5px 0px; } .mySlider-nav span{ display: inline-block; width: 0px; height: 0px; margin: 0 4px; padding: 3px; background: transparent; border-radius: 5px; border: 2px solid white; cursor: pointer; opacity: 0.7; } .mySlider-nav span.active{ background: white; } .mySlider-arrow{ top: 50%; position: absolute; width: 100%; } .mySlider-arrow span{ display: block; width: 32px; height: 32px; right: 15px; position: absolute; margin-top: -16px; overflow: hidden; background: rgba(0,0,0,.2) no-repeat 50% 50%; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAQCAQAAABuQZ3IAAAAi0lEQVR4AU3OISBEQQBAwS0AACS9NxqQgCZpkiYBVddFvWhAAUABAPQCAGC4g/0vTnrBqCfDIZl70J+kMUBPpEwT4FNXxBxz4F1HxHyr4EVTxBLb4EFNxEon4CJSlVNw9AcV9sC16h8osgke1P1ArgXwouVvdQq86ww/GQefusNf7kBviBlxpT8k+gL/Wox4r1d4MwAAAABJRU5ErkJggg=='); background-size: 7px 11px; border-radius: 32px; text-indent: -999em; opacity: .6; transition: opacity .2s; cursor: pointer; } .mySlider-arrow .prev{ left: 15px; transform: rotate(-180deg); } .mySlider-nav p{ display: block; border: 1px solid white; width: 60px; right: 0px; position: absolute; margin: 5px; padding: 2px; bottom: 0px; color: white; font-family: "微软雅黑"; }
接下来我们开始编写插件。首先确定这个幻灯片插件的名称,我们命名为:jquery.mySlider.js。按前面所描述的规范,整个插件应该写在一个闭包中:
(function($){ $.fn.mySlider = function(options){ /*...... */} })(jQuery);
接下来我们要确定插件的参数,并通过extend()
方法来实现用户自定义参数。
(function($){ $.fn.mySlider = function(options){ //设置插件的参数 var settings = $.extend({ autoplay: true, //是否自动播放 interval: 3000, //自动播放的时间间隔 speed: 400, //动画的速度 direction:'ltr' //从左到右或从右到左 },options || {}); } })(jQuery);
然后,我们可以设置一些需要的变量。
// 当前幻灯片的索引 var current = 0; // 幻灯片jQuery对象 var content = $(this); // ul元素 var ulElement = content.find("ul"); // li元素 var item = ulElement.find("li"); // 为实现无限循环效果进行图片分组 var group = item.length; // next导航按钮 var next = $(".next"); // prev导航按钮 var prev = $(".prev");
接下来,我们可以定义一个幻灯片对象slider
,在这个对象内部实现幻灯片的自动播放,下一帧和上一帧等功能。
var slider = { //幻灯片的初始化方法 init:function(){ timer = ''; // 自动播放的定时 if(item.length > 1){ ulElement.css({ 'width' : (item.length+2) * 100 + "%", 'margin-left': -100 + '%', 'left': 0 }); item.css({ 'float': 'left', 'listStyle': 'none', 'width': 100 / (item.length + 2) + '%' }); // 克隆列表元素,实现无限循环 ulElement.html(item.slice(0).clone()); ulElement.append(item.slice(0, 1).clone()); ulElement.prepend(item.slice(-1).clone()); } }, //自动播放 autoPlay: function() { var _this = this; if (settings.autoplay) { timer = setInterval(function() { if (settings.direction == 'ltr') { _this.toPrev(); } else { _this.toNext(); } }, settings.interval); } }, //停止自动播放 stopAuto: function() { if (settings.autoplay) { clearInterval(timer); } }, //幻灯片的动画函数 animate: function(num) { var _this = this; ulElement.animate({ left: -num * 100 + '%' }, settings.speed,function(){ if (num < 0) { current = group - 1; ulElement.css('left', -(group - 1) * 100 + '%'); } else if (num >= group) { current = 0; ulElement.css('left', 0); } else { current = num; } }) }, //跳转到下一帧 toNext: function() { current = current + 1; this.animate(current); }, //跳转到上一帧 toPrev: function() { current = current - 1; this.animate(current); } }
上面的实现代码都非常简单,并且每个方法都做了注释。最后,我们对幻灯片进行初始化,并开始自动播放,同时为前后导航按钮绑定鼠标的click事件。
slider.init(); slider.autoPlay(); next.on("click",function(event){ slider.toNext(); }) prev.on("click",function(event){ slider.toPrev(); })
到此,一个最简单的jQuery幻灯片插件就做好了。我们可以通过以下的方法来调用这个jQuery幻灯片插件:
$(function(){ $('.slider-warp').mySlider(); });
或者在调用时设置自定义参数:
$(function(){ $('.slider-warp').mySlider({ autoplay:false }); });
完整的jQuery代码如下:
(function($){ $.fn.mySlider = function(options){ var settings = $.extend({ autoplay: true, interval: 3000, speed: 400, direction:'ltr' },options || {}); var working; var current = 0; var content = $(this); var ulElement = content.find("ul"); var item = ulElement.find("li"); var group = item.length; var next = $(".next"); var prev = $(".prev"); var slider = { init:function(){ timer = ''; if(item.length > 1){ ulElement.css({ 'width' : (item.length+2) * 100 + "%", 'margin-left': -100 + '%', 'left': 0 }); item.css({ 'float': 'left', 'listStyle': 'none', 'width': 100 / (item.length + 2) + '%' }); ulElement.html(item.slice(0).clone()); ulElement.append(item.slice(0, 1).clone()); ulElement.prepend(item.slice(-1).clone()); } }, autoPlay: function() { var _this = this; if (settings.autoplay) { timer = setInterval(function() { if (settings.direction == 'ltr') { _this.toPrev(); } else { _this.toNext(); } }, settings.interval); } }, stopAuto: function() { if (settings.autoplay) { clearInterval(timer); } }, animate: function(num) { var _this = this; ulElement.animate({ left: -num * 100 + '%' }, settings.speed,function(){ if (num < 0) { current = group - 1; ulElement.css('left', -(group - 1) * 100 + '%'); } else if (num >= group) { current = 0; ulElement.css('left', 0); } else { current = num; } }) }, toNext: function() { current = current + 1; this.animate(current); }, toPrev: function() { current = current - 1; this.animate(current); } } slider.init(); slider.autoPlay(); next.on("click",function(event){ slider.toNext(); }) prev.on("click",function(event){ slider.toPrev(); }) return this; } })(jQuery);
来看一下这个jQuery幻灯片的效果吧!