为了顺利完成jquery插件的开发,细致阅读了jquery.grid.src.js 源码,感觉则个插件无论在效果显示,还是在使用方法上面,都非常方便。同时,给我们提供了封装jquery插件的良好思维。在此基础上,我借助jquery的另外一个插件jquery.datatables 封装了一个jquery.datatable.combox,来实现了输入框的下拉框选择功能。
在此,简单总结了一下开发jquery插件的方法:
1 命名规则:
a)插件的文件命名必须严格遵循jQuery.[插件名].js的规则,以便于与其他的js文件的区分,如新插件文件jquery.newplugin.js.
b)如果是对象级别插件,所有的方法都应依附于jquery.fn主体对象;如果是类级别插件,所有的方法都应依附于jquery对象
2 在开发之前需要对jquery相关技术点有一些理解
2.1 jquery中extend方法的使用
2.1.1 使用语法
extend(dest,src1,src2,src3...);
它的含义是将src1,src2,src3...合并到dest中,返回值为合并后的dest,由此可以看出该方法合并后,是修改了dest的结构的。如果想要得到合并的结果却又不想修改dest的结构,可以如下使用:
var newSrc=$.extend({},src1,src2,src3...)//也就是将"{}"作为dest参数
2.1.2 其它用法
extend(boolean,dest,src1,src2,src3...)
第一个参数boolean代表是否进行深度拷贝,其余参数和前面介绍的一致,什么叫深层拷贝,我们看一个例子:
var result=$.extend( true, {},
{name: "John", location: {city:"Boston",county:"USA"} },
{last: "Resig", location: {state:"MA",county:"China"} } );
我们可以看出src1中嵌套子对象location:{city:"Boston"},src2中也嵌套子对象location:{state:"MA"},第一个深度拷贝参数为true,合并结果:
result={name:"John",last:"Resig",
location:{city:"Boston",state:"MA",county:"China"}}
如果第一个参数boolean为false,则合并结果:
result={name:"John",last:"Resig",location:{state:"MA",county:"China"}}
2.2 call与apply的用法
通过一个例子简单说明这两个的用法:
var test="Tony";
var myobj={
test : "Tom"
};
function doSomething(name, age){
alert(this.test + ":" + name + age);
}
doSomething("Tony",23);//普通调用结果Tony:Tony23
doSomething.call(myobj,"Tony",23);//call调用结果Tom:Tony23
doSomething.apply(object,["Tony",23]);//apply调用结果与call相同
2.3 对闭包的理解
2.3.1 一句话解释一下:闭包就是函数的函数,内部函数作为外部函数的返回
通过一个简单example了解一下:
function a() {
var i = 0;
function b() {
alert(++i);
}
return b;
}
var c = a();
c(); //1
c(); //2
有这个例子可以看出,由于闭包的存在使得函数a返回后,a中的i始终存在,这样每次执行c(),i都是自加1后alert出i的值。
那么我们来想象另一种情况,如果a返回的不是函数b,情况就完全不同了。因为a执行完后,b没有被返回给a的外界,只是被a所引用,而此时a也只会被b引用,因此函数a和b互相引用但又不被外界打扰(被外界引用),函数a和b就会被GC回收。
这段代码有两个特点:
(1)函数b嵌套在函数a内部;
(2)函数a返回函数b。
这样在执行完var c = a()后,变量c实际上是指向了函数b,再执行c()后就会弹出一个窗口显示i的值(第一次为1)。
这段代码其实就创建了一个闭包,为什么?因为函数a外的变量c引用了函数a内的函数b,就是说:当函数a的内部函数b被函数a外的一个变量引用的时候,就创建了一个闭包。
2.3.2 js中的get和set
var db = (function() {
//创建一个隐藏的object, 这个object持有一些数据,从外部是不能访问这个object的
var data = {};
//创建一个函数, 这个函数提供一些访问data的数据的方法
return function(key, val) {
if(val === undefined) {
return data[key] } //get
else{ return data[key] = val } //set
}
//我们可以调用这个匿名方法
//返回这个内部函数,它是一个闭包
})();
var res1 = db('x'); //返回 undefined
var res2 = db('x',1); //设置data['x']为1
var res3 = db('x');//返回 1
var res4 = db('y',2); //设置data['y']为2
var res5 = db('y');//返回 2
alert(res1+"-"+res2+"-"+res3+"= "+res4+"-"+res5);
通过上面的例子,我们可以看出闭包的作用就是在a执行完并返回后,闭包使得Javascript的垃圾回收机制GC不会收回a所占用的资源,因为a的内部函数b的执行需要依赖a中的变量。
2.4 理解代码:“;(function( $, window, document, undefined ){ //函数体内具体代码 })(jQuery, window,document);”
a)代码最前面的分号,可以防止多个文件压缩合并以为其他文件最后一行语句没加分号,而引起合并后的语法错误。
b)(function ($, window, document, undefined ):声明一个匿名函数,括号中是形参。$是jQuery的简写,添加形参undefined是因为undefined在老一辈的浏览器是不被支持的,直接使用会报错,js框架要考虑到兼容性,因此增加一个形参undefined
c){ //函数体内具体代码 })(jQuery,window,document);最后的小括号的意思是立即执行这个匿名函数,括号中是实参。
3 开发插件类型
jQuery插件包括两种插件,一种是类级别的插件开发,即给jQuery添加全局方法。另一种是对象级别的插件开发,即给jQuery对象添加方法。下面将对这两种开发简单做简单说明
3.1 给jQuery添加全局函数
3.1.1 我们只需要定义如下:
jQuery.fun_1 = function(){
alert("thisis a first function");
}
jQuery.fun_2 = function(param){
alert("thefunction take a param,which is "+param);
}
调用方法:jQuery.fun_1(); $.fun_2("test");
3.1.2 使用extend扩展
code如下:
jQuery.extend({
fun_1:function(){
alert("thisis a first function");
},
fun_2:function(param){
alert("thefunction take a param,which is "+param);
}
})
调用方法:jQuery.fun_1(); $.fun_2("test");
3.1.3 使用命名空间
方法一:
jQuery.newPlugin={
fun_1:function(){
alert("thisis a first function");
},
fun_2:function(param){
alert("thefunction take a param,which is "+param);
}
}
方法二:
这个方法使用extend实现带有命名空间的jQuery全局函数,code如下:
$.newPlugin = $.newPlugin || {};
jQuery.extend($.newPlugin,{
fun_1:function(){
alert("thisis a first function");
},
fun_2:function(param){
alert("thefunction take a param,which is "+param);
}
})
3.2 对象级别的插件开发
方法一:
(function($){
$.fn.newPlugin= function(){
}
})(jQuery)
方法二:
(function($){
$.fn.extend({
newPlugin:function(){
}
})
})(jQuery)
以上两个方法均使用了匿名函数,其形参是$,在定义完成之后,立即调用并将jQuery对象实参传给它
在下面将以方法一中的方式来做其它特性说明
3.2.1 通过参数options控制插件行为
(function($){
$.fn.newPlugin= function(options){
vardefaults={
width:"100px",
height:"50px",
backgroud:"red",
clickEvent:null
}
//将默认属性和插件初始化的时候设置的属性进行整合,这儿要注意extend的用法
$.extend(defaults,options);
}
})(jQuery)
使用方法:$("#div_id").newPlugin({width:"500px"});
3.2.2 暴漏一些函数,并定义私有方法
(function($){
$.fn.newPlugin= function(options){
vardefaults={
width:"100px",
height:"50px",
backgroud:"red",
clickEvent:null
}
//将默认属性和插件初始化的时候设置的属性进行整合,这儿要注意extend的用法
$.extend(defaults,options);
returnthis.each(function(){
varts = this;
})
}
//在页面上访问方法:$.fn.newPlugin.fun_test();
$.fn.newPlugin.fun_test= function(){
alert("fun_test");
}
functionprivateFun(){
alert("thisis a private function");
}
})(jQuery)
3.2.3 根据参数设置,给对象添加事件
(function($){
$.fn.newPlugin= function(options){
vardefaults={
width:"100px",
height:"50px",
backgroud:"red",
clickEvent:null
}
//将默认属性和插件初始化的时候设置的属性进行整合,这儿要注意extend的用法
$.extend(defaults,options);
returnthis.each(function(){
varts=this;
//给返回对象中的button添加点击事件
if(clickEvent){
$(ts).find("button"),bind("click",function(){
clickEvent.call();
})
}
})
}
//在页面上访问方法:$.fn.newPlugin.fun_test();
$.fn.newPlugin.fun_test= function(){
alert("fun_test");
}
functionprivateFun(){
alert("thisis a private function");
}
})(jQuery)