jQuery插件开发

一般来说,jQuery插件的开发分为两种:一种是挂在jQuery命名空间下的全局函数,也可称为静态方法;另一种是jQuery对象级别的方法,即挂在jQuery原型下的方法,这样通过选择器获取的jQuery对象实例也能共享该方法。

一、在讲解jQuery插件基本结构和模式前,先介绍下两个重要的方法,还有不知啥原因,代码无法折叠,导致整体篇幅稍微有点长,阅读时请加点耐心:

1、$.extend(target, [object1], [objectN])

该方法主要用于合并两个或更多对象的内容(属性)到第一个对象,并返回合并后的第一对象。如果该方法只有一个参数target,则该参数将扩展jQuery的命名空间,即作为静态方法挂在jQuery全局对象下,如jQuery里的$.ajax、$.getJSON全局函数等:

// 将hello方法挂在jquery全局对象下,作为静态方法
$.extend({
hello: function() {alert("hello");}
});

又如,在jQuery全局对象中扩展一个hcy命名空间:

$.extend({ hcy: { } });

并将hello方法扩展到之前扩展的JQuery的hcy命名空间中去:

$.extend($.hcy, {
hello: function() {alert("hello");}
});

在开发插件时,也可以将方法扩展到jQuery的原型中去,如:

$.extend($.fn, {
hello: function() {alert("hello");}
});

值得注意的是:多个对象参数合并时,会破坏第一个对象的结构,所以可传递一个空对象作为第一个参数,如:$.extend({}, object1, object2);

另外,对于深度拷贝,即如果对象中也嵌套子对象,则会拷贝并覆盖子对象(如果有同名属性)全部的属性,需要设置第一个参数deep为true值,如:$.extend(true, target, object1, [objectN])。

2、$.fn.extend(target)

在jQuery中,$.fn本质上是等于jQuery的原型,即$.fn = $.prototype, 所以该方法实际上是为jQuery原型添加方法,即把target对象的方法添加到jQuery原型中去,这样jQuery对象实例就可以访问添加的方法了,这也是jQuery插件开发常用的方法,特别是添加多个接口时。如:

// 将hello、hello2方法添加到jquery原型中
$.fn.extend({
hello: function() {alert("hello!");},
hello2: function() {alert("hello again!);}
});

如果添加单个方法到jQuery原型中,可使用$.fn.pluginName方法添加,如:

// 将hello方法添加到jquery原型中
$.fn.hello = function() {
// ...
};

二、在开发过一些 jQuery 插件后,慢慢的探索出了一套开发jQuery插件的基本结构和模式。这样在面对复杂多变的需要方案时,只要专注最主要的逻辑代码就行了。另外,使用相同的设计模式和架构也让修复bug或者二次开发更容易。

在这里分享一些平时遇到和总结的经验:

1、把全部代码放在闭包(一个即时执行函数)里

此时闭包相当于一个私有作用域,外部无法访问到内部的信息,并且不会存在全局变量的污染情况。官方创建开发规范的解释是:a) 避免全局依赖;b) 避免第三方破坏;c) 兼容jQuery操作符'$'和'jQuery '。如下所示:

(function($) {
// 局部作用域中使用$来引用jQuery
// ...
})(jQuery);

这段代码在被解析时可理解成以下代码:

var jQ = function($) {
// code goes here
};
jQ(jQuery);

2、提供插件的默认参数选项

一个扩展性良好的插件应该是可以让使用者根据需求自定义参数选项,并控制插件的行为,所以提供恢复默认选项是很有必要的。你可以通过jQuery的extend方法来设置这些选项:

var defaults = {
name: "hcy",
age: 22,
job: "student",
walk: function() {
// ...
}
};

$.extend({}, defaults, options || {});

注:参数选项设置时也可以使用如下模式,即把参数对象挂在插件命名空间下:

$.fn.pluginName.defaults = {
name: "hcy",
age: 22,
job: "student",
walk: function() {
// ...
}
};

3、遍历多个元素并返回

jQuery使用Sizzle选择器引擎,Sizzle可以为你的函数提供多元素操作(例如对所有类名相同的元素)。这是jQuery几个优秀的特性之一,在开发插件过程中即使你不准备为你的插件提供多元素支持,但为这做准备仍然是一个很好的实践。另外,jQuery有一个很好的特点就是可以进行方法级联,也可称为链式调用,所以我们不应该破坏这个特性,始终在方法中返回一个元素。如:

function($) {
// 参数选项设置...
// 向jQuery原型中添加你的插件代码,用“pluginName”作为插件的函数名称。
$.fn.pluginName = function(options) {
// 遍历匹配的元素||元素集合,并返回this,以便进行链式调用。
return this.each(function() {
// 此处可通过this来获得每个单独的元素(jQuery对象)
var $this = $(this); });
};
})(jQuery);

4. 一次性代码放在主循环以外

这一条很重要,但是常常被忽略。简单的讲,如果你有一段代码是一堆默认值,只需要被实例化一次,而不是每次调用你插件功能的时候都需要实例化,你应该把这段代码放在插件方法的外面。这样可以让你的插件运行的更高效,节省内存。如:

function($) {
// 参数选项设置
var defaults = {
name: "hcy",
age: 22,
job: "student",
walk: function() {
// ...
}
};
// 向jQuery原型中添加你的插件代码,用“pluginName”作为插件的函数名称。
$.fn.pluginName = function(options) {
var opts = $.extend({}, defaults, options || {}); // 遍历匹配的元素||元素集合,并返回this,以便进行链式调用。
return this.each(function() {
// 此处可通过this来获得每个单独的元素(jQuery对象)
var $this = $(this);
// ...
});
};
})(jQuery);

5、定义公有方法和私有方法

一般情况下,对于一个jQuery插件,一个基本的函数就可以很好地工作,但是对于复杂一点的插件就需要提供各种各样的方法和私有函数。你可能会使用不同的命名空间去为你的插件提供各种方法,但是添加过多的命名空间反而会使代码变得混乱,健壮性下降。所以最好的解决办法是适当地定义私有函数和方法。例子如下所示:

(function($) {
// 在我们插件容器内,定义一个私有方法
var privateFunction = function() {
// code here
}; // 通过字面量创造一个对象,存储我们需要的共有方法
var methods = {
// 在字面量对象中定义每个单独的方法
init: function() {
// 为了更好的灵活性,对来自主函数,并进入每个方法中的选择器其中的每个单独的元素都执行代码
return this.each(function() {
// 为每个独立的元素创建一个jQuery对象
var $this = $(this);
// 执行代码 例如:privateFunction()
});
},
destroy: function() {
// 对选择器每个元素都执行方法
return this.each(function() {
// 执行代码
});
}
}; $.fn.pluginName = function() {
// 获取我们的方法,遗憾的是,如果我们用function(method){}来实现,这样会毁掉一切的
var method = arguments[0]; // 检验方法是否存在
if(methods[method]) {
// 如果方法存在,存储起来以便使用
// 注意:我这样做是为了等下更方便地使用each()
method = methods[method]; // 如果方法不存在,检验对象是否为一个对象(JSON对象)或者method方法没有被传入
} else if (typeof method === "object" || !method ) {
// 如果我们传入的是一个对象参数,或者根本没有参数,init方法会被调用
method = methods.init;
} else {
// 如果方法不存在或者参数没传入,则报出错误。需要调用的方法没有被正确调用
$.error("Method" + method + "does not exist on jQuery.pluginName");
return this;
} // 调用我们选中的方法
// 再一次注意我们是如何将each()从这里转移到每个单独的方法上的
return method.call(this);
}; })(jQuery);

注意我把 privateFunction 当做了一个函数内部的全局变量。考虑到所有的代码的运行都是在插件容器内进行的,所以这种做法是可以被接受的,因为它只在插件的作用域中可用。在插件中的主函数(pluginName)中,我检验了传入参数所指向的方法是否存在。如果方法不存在或者传入的是参数为对象, init 方法会被运行。最后,如果传入的参数不是一个对象而是一个不存在的方法,我们会报出一个错误信息。

下面是一些用法的例子

// 为每个类名为 ".className" 的元素执行init方法
$(".className").pluginName();
$(".className").pluginName("init");
$(".className").pluginName("init", {}); // 向init方法传入“{}”对象作为函数参数
$(".className").pluginName({}); // 向init方法传入“{}”对象作为函数参数 // 为每个类名为 “.className” 的元素执行destroy方法
$(".className").pluginName("destroy");
$(".className").pluginName("destroy", {}); // 向destroy方法传入“{}”对象作为函数参数 // 所有代码都可以正常运行
$(".className").pluginName("init", "argument1", "argument2"); // 把 "argument1" 和 "argument2" 传入 "init" // 不正确的使用
$(".className").pluginName("nonexistantMethod");
$(".className").pluginName("nonexistantMethod", {});
$(".className").pluginName("argument1"); // 会尝试调用 "argument1" 方法
$(".className").pluginName("argument1", "argument2"); // 会尝试调用 "argument1" ,“argument2”方法
$(".className").pluginName("privateFunction"); // "privateFunction" 不是一个方法

注明:该例子代码参考伯乐在线的一篇文章。

 6、添加持久性数据

在插件开发过程中,有时需要在插件中保存设置和信息,这时jQuery中的$.data函数就可以派上用场了。使用时,它会尝试获取和元素相关的数据,如果数据不存在,它就会创造相应的数据并添加到元素上。一旦你使用了$.data来为元素添加信息,请确认你已经记住remember,当不再需要数据的时候,用$.removeData函数来删除相应的数据。下面的例子也同样摘自伯乐在线一篇文章(深入理解jQuery插件开发)里的一小段:

(function($) {
var privateFunction = function() {
// 执行代码
} var methods = {
init: function(options) { // 在每个元素上执行方法
return this.each(function() {
var $this = $(this); // 尝试去获取settings,如果不存在,则返回“undefined”
var settings = $this.data("pluginName"); // 如果获取settings失败,则根据options和default创建它
if (typeof settings === "undefined") { var defaults = {
propertyName: "value",
onSomeEvent: function() {}
}; settings = $.extend({}, defaults, options); // 保存我们新创建的settings
$this.data("pluginName", settings);
} else {
/ 如果我们获取了settings,则将它和options进行合并(这不是必须的,你可以选择不这样做)
settings = $.extend({}, settings, options); // 如果你想每次都保存options,可以添加下面代码:
// $this.data("pluginName", settings);
} // 执行代码 });
},
destroy: function(options) {
// 在每个元素中执行代码
return $(this).each(function() {
var $this = $(this); // 执行代码 // 删除元素对应的数据
$this.removeData("pluginName");
});
},
val: function(options) {
// 这里的代码通过.eq(0)来获取选择器中的第一个元素的,我们或获取它的HTML内容作为我们的返回值
var someValue = this.eq(0).html(); // 返回值
return someValue;
}
}; $.fn.pluginName = function() {
var method = arguments[0]; if (methods[method]) {
method = methods[method];
arguments = Array.prototype.slice.call(arguments, 1);
} else if (typeof method === "object" || !method ) {
method = methods.init;
} else {
$.error("Method" + method + "does not exist on jQuery.pluginName");
return this;
} return method.apply(this, arguments); } })(jQuery);

在上面的代码中,首先检验元素的数据是否存在。如果数据不存在,“options”和“default”会被合并,构建成一个新的settings,然后用$.data()保存在元素中。

结语:终于要到结语了╮(╯▽╰)╭,整体介绍下来,部分参考别人的例子,加入自己的理解和思考,在方便了自己的同时希望对阅读的童鞋有所帮助。在jQuery插件开发的道路上任重道远( ⊙ o ⊙ )啊!加油↖(^ω^)↗

因为分享,所以简单;因为分享,所以快乐。
 
http://www.cnblogs.com/cyStyle/archive/2013/05/18/jQuery%E6%8F%92%E4%BB%B6%E8%AF%A6%E7%BB%86%E5%BC%80%E5%8F%91.html

jQuery插件开发的模式和结构的更多相关文章

  1. jquery学习笔记---插件开发模式和结构

    JQuery插件开发http://www.cnblogs.com/damonlan/archive/2012/04/06/2434460.html github教程:https://github.co ...

  2. jQuery插件开发模式

    jQuery插件开发模式 软件开发过程中是需要一定的设计模式来指导开发的,有了模式,我们就能更好地组织我们的代码,并且从这些前人总结出来的模式中学到很多好的实践. 根据<jQuery高级编程&g ...

  3. (转)jQuery插件开发模式

    要说jQuery 最成功的地方,我认为是它的可扩展性吸引了众多开发者为其开发插件,从而建立起了一个生态系统.这好比大公司们争相做平台一样,得平台者得天下.苹果,微软,谷歌等巨头,都有各自的平台及生态圈 ...

  4. JQuery插件开发初探——结构熟悉

    工作之余,对Jquery插件做了一点尝试,想着之前总用别人写的插件,自己要是也写一个用岂不是很cool.于是说干就干,动手开始写. 首先是模仿,从一个简单的功能进行入手,了解一下插件开发的流程和结构. ...

  5. 浅谈jquery插件开发模式

    首先根据<jQuery高级编程>的描述来看,jQuery插件开发方式主要有三种: 通过$.extend()来扩展jQuery 通过$.fn 向jQuery添加新的方法 通过$.widget ...

  6. jQuery插件开发精品教程,让你的jQuery提升一个台阶

    要说jQuery 最成功的地方,我认为是它的可扩展性吸引了众多开发者为其开发插件,从而建立起了一个生态系统.这好比大公司们争相做平台一样,得平台者得天下.苹果,微软,谷歌等巨头,都有各自的平台及生态圈 ...

  7. 从零开始学jQuery插件开发

    http://www.w3cfuns.com/notes/19462/ec18ab496b4c992c437977575b12736c.html jQuery 最成功的地方,是它的可扩展性,通过吸引了 ...

  8. jquery插件开发继承了jQuery高级编程思路

    要说jQuery 最成功的地方,我认为是它的可扩展性吸引了众多开发者为其开发插件,从而建立起了一个生态系统.这好比大公司们争相做平台一样,得平台者得天下.苹果,微软,谷歌等巨头,都有各自的平台及生态圈 ...

  9. Jquery插件开发精品教程

    最开始接触jquery对他提供的各种插件总是十分有兴趣,但是总是不理解为什么这样写,从网络上查询了很久终于找到这篇文章,讲解的很详细,分享给大家. 要说jQuery 最成功的地方,我认为是它的可扩展性 ...

随机推荐

  1. linux下修改tomcat的默认目录

    1.修改tomcat的默认目录.它的默认目录是webapps/ROOT,对应的conf目录下的server.xml里的内容是: 1.修改tomcat的默认目录.它的默认目录是webapps/ROOT, ...

  2. 查找当前SQL Server下的Active Session正连接着哪个数据库

    今天碰到个事.原本想把数据库设为单用户模式然后把REMOVE FILE.没想到悲剧了.因为很多进程都是需要远程连接这个库,导致别的进程抢在我前面连接了这个数据库,反到我连不上了.想把数据库切回MULT ...

  3. JSON对象末尾多余逗号问题

    平时开发用的IE10,没发现这个问题,测试人员对系统兼容性测试时发现了在IE7下存在问题. 问题代码如下: var person = { name: "John", age: 25 ...

  4. 我 Git 命令列表 (1)【转】

    转自:http://www.microsofttranslator.com/bv.aspx?from=en&to=zh-CHS&a=http%3A%2F%2Fvincenttam.gi ...

  5. Ubuntu 14.04怎样升级到Ubuntu 14.10

    Ubuntu 14.04怎样升级到Ubuntu 14.10     Ubuntu 14.10 Utopic Unicorn 将在10月23日正式发布,9月25日最终测试版本已经发布,Ubuntu 14 ...

  6. [原]HDU-1598-find the most comfortable road(暴力枚举+Kruskal最小生成树)

    题意: 给出一个图,然后Q个询问,每次询问从一个节点到另一个节点,联通图中的“最大边和最小边之差”的最小值,但如果节点之间不连通,则输出-1. 思路:由于询问Q < 11,m < 1000 ...

  7. 《c程序设计语言》读书笔记-字符型0-9转为数字0-9

    #include <stdio.h> #define Num 10 int atoi(char s[]); int main() { int c,i = 0; char s[Num]; i ...

  8. XTU -1231 人生成就 (dp + 记录最优解的个数)

    http://202.197.224.59/OnlineJudge2/index.php/Problem/read/id/1231 直接递推. 在保存最大值的时候同时保存有多少条到达最大值的路径,注意 ...

  9. kettle创建资源库

    手动修改一下这个表 R_VERSION INSERT INTO R_VERSION(ID_VERSION, MAJOR_VERSION, MINOR_VERSION, UPGRADE_DATE, IS ...

  10. 加密解密(5)SSL形象比喻

    转自: http://blog.csdn.net/cloverphp/article/details/11737433 前言: 关于公钥,私钥请看前几篇文章   SSL 协议既用到了公钥加密技术(握手 ...