学习随记前端踩坑专题天干物燥,前端别闹

JS封装——构建自己的jQuery插件

2017-03-13  本文已影响3561人  o黄裳元吉o

参与的多个项目有时候需要复用一些功能,那么就希望能把一些功能进行封装,提高易用性和代码复用性。
直接上个简单的栗子,详情见imageCarousel

 (function ( $, window, document) {
    var pluginName = "imageCarousel",
    
    //默认配置参数  default settings
    defaults = {
        speed:300,    //滑动速度 slide speed
        autoSlide:true,    //是否主动滑动 slide automatically
        holdTime:4000,      //主动滑动时图片停留时间 the time to hold image between two slidings
        alwaysShowTitle:true, //是否一直显示图片标题 
        color:"#000",   //字体颜色 font color
        clickImage:function(element,index){}, //点击图片时回调函数,参数:element:图片元素,index:图片在图片数组中的序号
    };
    
    // The actual plugin constructor
    function Plugin ( element, images,options ) {
            this.element = element;
            this.images = images;
            this.settings = $.extend( {}, defaults, options );
            this._defaults = defaults;
            this._name = pluginName;
            this.init();
    };
    
    Plugin.prototype = {
            init: function () {   //初始化
                var e = this;
                e.width = $(e.element).width();
                e.height = $(e.element).height();
                $(e.element).addClass("imageCarouselBox");
                $(e.element).css("color",e.settings.color);
                e.picTimer;
                e.setImages(e.images);
            },
                        
            setImages:function(images){  //设置图片数组,可以用于修改当前播放的图片数组
                var e = this;
                e.dataLength = e.images.length;
                $(e.element).html("");
                e.index = 0;
                var ulText = "<ul>"
                var btnText = "<div class='btnBg'><div class='btn'>";
                for(var i=0; i < e.dataLength; i++) {
                    btnText += "<span></span>";
                    ulText += "<li ><img src='"+images[i].path+"' alt='' ><div class='text-box'>"+images[i].title+"</div></li>"; //插入图片
                }
                btnText += "</div></div><div class='preNext pre'></div><div class='preNext next'></div>";
                ulText += "</ul>";
                
                $(e.element).append(ulText);
                $(e.element).append(btnText);
                
                $(e.element).find("ul").css("width",e.width * e.dataLength);
                $(e.element).find("ul li").css("width",e.width).click(function(){
                    e.settings.clickImage(this,e.index);
                });
                if(e.settings.alwaysShowTitle){
                    $(e.element).find("ul li .text-box").fadeIn();
                } else{
                    $(e.element).find("ul li").mouseenter(function(){
                        $(this).find(".text-box").fadeIn();
                    }).mouseleave(function(){
                        $(this).find(".text-box").fadeOut();
                    });
                }
                
                $(e.element).find(".btn span").css("opacity",0.4).mouseenter(function() {
                    e.index = $(e.element).find(".btn span").index(this);
                    e.showImage(e.index);
                }).eq(0).trigger("mouseenter");
                
                $(e.element).find(" .preNext").css("opacity",0.2).hover(function() {
                    $(this).stop(true,false).animate({"opacity":"0.5"},e.settings.speed);
                },function() {
                    $(this).stop(true,false).animate({"opacity":"0.2"},e.settings.speed);
                });
                
                $(e.element).find(" .pre").click(function() {
                    e.index -= 1;
                    if(e.index == -1) {e.index = e.dataLength - 1;}
                    e.showImage(e.index);
                });
                $(e.element).find(" .next").click(function() {
                    e.index += 1;
                    if(e.index == e.dataLength) {e.index = 0;}
                    e.showImage(e.index);
                });
                
                if(e.settings.autoSlide){
                    $(e.element).hover(function() {
                        clearInterval(e.picTimer);
                    },function() {
                        e.picTimer = setInterval(function() {
                            e.showImage(e.index);
                            e.index++;
                            if(e.index == e.dataLength) {e.index = 0;}
                        },e.settings.holdTime); 
                    }).trigger("mouseleave");
                }
            },
        
            showImage: function(index){  //切换当前显示的图片
                var e = this;
                var nowLeft = -index*e.width;
                $(e.element).find("ul").stop(true,false).animate({"left":nowLeft},e.settings.speed);
                $(e.element).find(" .btn span").stop(true,false).animate({"opacity":"0.4"},e.settings.speed)
                  .eq(index).stop(true,false).animate({"opacity":"0.8"},e.settings.speed);
            }
        };

    $.fn[ pluginName ] = function ( images,options) {   //向jQuery注册插件
        var e = this;
        e.each(function() {
            $.data( e, "plugin_" + pluginName, new Plugin( this,images, options ) );
        });
        return e;
    };
    
})(jQuery, window, document)

以上代码封装了一个jQuery图片轮播插件。

1. 用匿名函数封装组件

首先看看如下写法:

(function ( $, window, document) {
  //....封装组件逻辑
})(jQuery, window, document);

这就是一个匿名函数的形式。将它拆开来看如下:

var fn = function($, window, document){
  //....封装组件逻辑
};
fn(jQuery, window, document);

也就是说这种写法就表示先定义一个方法,然后立即调用这个方法,jQuery相当于实参。打开jquery.js的原文件可以看到,jQuery是这个文件里面的一个全局变量。

2. 向jQuery注册组件

先直接看上面栗子的最后几行代码:

$.fn[ pluginName ] = function ( images,options) {   //向jQuery注册插件
    var e = this;
    e.each(function() {
        $.data( e, "plugin_" + pluginName, new Plugin( this,images, options ) );
    });
    return e;
};

由于在栗子最前面我们定义了

var pluginName = "imageCarousel";

那么

$.fn[ pluginName ] = function ( images,options) { 
  //...
}

在jQuery中注册了一个名为imageCarousel的函数及其参数,与jQuery自带的函数一样,可以通过以下方法调用:

$(element).imageCarousel(images,options);

e.each(function() {
    $.data( e, "plugin_" + pluginName, new Plugin( this,images, options ) );
});

则向当前元素添加了一个名为“plugin_imageCarousel”的属性,它的值为 new Plugin( element,images, options )。
也就是说,

$(element).imageCarousel(images,options);

这行代码实际上会向元素中添加“plugin_imageCarousel”属性,并执行了:

$(element).plugin_imageCarousel = new Plugin( element,images, options );

3. 定义组件的构造函数

function Plugin ( element, images,options ) {
    this.element = element;
    this.images = images;
    this.settings = $.extend( {}, defaults, options );
    this._defaults = defaults;
    this._name = pluginName;
    this.init();
};

构造函数保护了插件的各个参数包括默认参数,然后调用了插件的 prototype 中定义的 init 方法。

4. 定义插件的行为

imageCarousel 插件在 Plugin.prototype中定义了init()、setImages(images)、showImage(index)这几个函数,具体作用不用展开说明。这些函数可以用以下方法调用:

$(element).plugin_imageCarousel.init();
$(element).plugin_imageCarousel.setImages(images);
$(element).plugin_imageCarousel.showImage(index);

5. 定义组件的配置参数

有时候我们希望能够自定义组件的一些属性或行为,那么就可以定义一组配置参数:

//默认配置参数  default settings
    defaults = {
        speed:300,    //滑动速度 slide speed
        autoSlide:true,    //是否主动滑动 slide automatically
        holdTime:4000,      //主动滑动时图片停留时间 the time to hold image between two slidings
        alwaysShowTitle:true, //是否一直显示图片标题 
        color:"#000",   //字体颜色 font color
        clickImage:function(element,index){}, //点击图片时回调函数,参数:element:图片元素,index:图片在图片数组中的序号
    };

这些参数预先设置了默认值,那么在使用的时候是如何自定义的呢?
在组件的构造函数中可以看到这样一句代码:

...
this.settings = $.extend( {}, defaults, options );
...

jquery的extend()方法作用是合并另个对象,有相同的则覆盖,没有相同的则添加。也就是说,上面这行代码中options对象中的参数会覆盖defaults对象中同名的参数,这就实现了配置参数自定义的目的。

上一篇下一篇

猜你喜欢

热点阅读