JS封裝——構(gòu)建自己的jQuery插件

參與的多個(gè)項(xiàng)目有時(shí)候需要復(fù)用一些功能,那么就希望能把一些功能進(jìn)行封裝,提高易用性和代碼復(fù)用性。
直接上個(gè)簡(jiǎn)單的栗子,詳情見(jiàn)imageCarousel

 (function ( $, window, document) {
    var pluginName = "imageCarousel",
    
    //默認(rèn)配置參數(shù)  default settings
    defaults = {
        speed:300,    //滑動(dòng)速度 slide speed
        autoSlide:true,    //是否主動(dòng)滑動(dòng) slide automatically
        holdTime:4000,      //主動(dòng)滑動(dòng)時(shí)圖片停留時(shí)間 the time to hold image between two slidings
        alwaysShowTitle:true, //是否一直顯示圖片標(biāo)題 
        color:"#000",   //字體顏色 font color
        clickImage:function(element,index){}, //點(diǎn)擊圖片時(shí)回調(diào)函數(shù),參數(shù):element:圖片元素,index:圖片在圖片數(shù)組中的序號(hào)
    };
    
    // 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){  //設(shè)置圖片數(shù)組,可以用于修改當(dāng)前播放的圖片數(shù)組
                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){  //切換當(dāng)前顯示的圖片
                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注冊(cè)插件
        var e = this;
        e.each(function() {
            $.data( e, "plugin_" + pluginName, new Plugin( this,images, options ) );
        });
        return e;
    };
    
})(jQuery, window, document)

以上代碼封裝了一個(gè)jQuery圖片輪播插件。

1. 用匿名函數(shù)封裝組件

首先看看如下寫法:

(function ( $, window, document) {
  //....封裝組件邏輯
})(jQuery, window, document);

這就是一個(gè)匿名函數(shù)的形式。將它拆開來(lái)看如下:

var fn = function($, window, document){
  //....封裝組件邏輯
};
fn(jQuery, window, document);

也就是說(shuō)這種寫法就表示先定義一個(gè)方法,然后立即調(diào)用這個(gè)方法,jQuery相當(dāng)于實(shí)參。打開jquery.js的原文件可以看到,jQuery是這個(gè)文件里面的一個(gè)全局變量。

2. 向jQuery注冊(cè)組件

先直接看上面栗子的最后幾行代碼:

$.fn[ pluginName ] = function ( images,options) {   //向jQuery注冊(cè)插件
    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中注冊(cè)了一個(gè)名為imageCarousel的函數(shù)及其參數(shù),與jQuery自帶的函數(shù)一樣,可以通過(guò)以下方法調(diào)用:

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

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

則向當(dāng)前元素添加了一個(gè)名為“plugin_imageCarousel”的屬性,它的值為 new Plugin( element,images, options )。
也就是說(shuō),

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

這行代碼實(shí)際上會(huì)向元素中添加“plugin_imageCarousel”屬性,并執(zhí)行了:

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

3. 定義組件的構(gòu)造函數(shù)

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

構(gòu)造函數(shù)保護(hù)了插件的各個(gè)參數(shù)包括默認(rèn)參數(shù),然后調(diào)用了插件的 prototype 中定義的 init 方法。

4. 定義插件的行為

imageCarousel 插件在 Plugin.prototype中定義了init()、setImages(images)、showImage(index)這幾個(gè)函數(shù),具體作用不用展開說(shuō)明。這些函數(shù)可以用以下方法調(diào)用:

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

5. 定義組件的配置參數(shù)

有時(shí)候我們希望能夠自定義組件的一些屬性或行為,那么就可以定義一組配置參數(shù):

//默認(rèn)配置參數(shù)  default settings
    defaults = {
        speed:300,    //滑動(dòng)速度 slide speed
        autoSlide:true,    //是否主動(dòng)滑動(dòng) slide automatically
        holdTime:4000,      //主動(dòng)滑動(dòng)時(shí)圖片停留時(shí)間 the time to hold image between two slidings
        alwaysShowTitle:true, //是否一直顯示圖片標(biāo)題 
        color:"#000",   //字體顏色 font color
        clickImage:function(element,index){}, //點(diǎn)擊圖片時(shí)回調(diào)函數(shù),參數(shù):element:圖片元素,index:圖片在圖片數(shù)組中的序號(hào)
    };

這些參數(shù)預(yù)先設(shè)置了默認(rèn)值,那么在使用的時(shí)候是如何自定義的呢?
在組件的構(gòu)造函數(shù)中可以看到這樣一句代碼:

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

jquery的extend()方法作用是合并另個(gè)對(duì)象,有相同的則覆蓋,沒(méi)有相同的則添加。也就是說(shuō),上面這行代碼中options對(duì)象中的參數(shù)會(huì)覆蓋defaults對(duì)象中同名的參數(shù),這就實(shí)現(xiàn)了配置參數(shù)自定義的目的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 作為一個(gè)前端er,如果不會(huì)寫一個(gè)小插件,都不好意思說(shuō)自己是混前端界的。寫還不能依賴jquery之類的工具庫(kù),否則裝...
    綽號(hào)陸拾柒閱讀 46,489評(píng)論 42 261
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,281評(píng)論 25 708
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,680評(píng)論 19 139
  • Swift版本點(diǎn)擊這里歡迎加入QQ群交流: 594119878最新更新日期:18-09-17 About A cu...
    ylgwhyh閱讀 26,252評(píng)論 7 249
  • 當(dāng)我撕開自己的面紗,我看到背后的傷痛,那份傷痛它在很久以前就植入我的身體的每一個(gè)細(xì)胞,它被太多的不允許,它不許我脆...
    徐愷嶸閱讀 300評(píng)論 0 0

友情鏈接更多精彩內(nèi)容