当前位置主页 > 资料库 > 前端教程 > jQuery教程-编写jQuery插件

jQuery教程-编写jQuery插件

2016-03-04

在网上有各种各样的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的nameage属性会被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 ) {
      //......
  }
};                              
                            

原来$.fnjQuery.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幻灯片的效果吧!

相关阅读
Previous:
上一篇:jQuery教程-jQuery动画
Next:
下一篇:jQuery教程-jQuery中的Ajax操作

我要评论

返回顶部