JS封装——构建自己的jQuery插件
参与的多个项目有时候需要复用一些功能,那么就希望能把一些功能进行封装,提高易用性和代码复用性。
直接上个简单的栗子,详情见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对象中同名的参数,这就实现了配置参数自定义的目的。