(翻译)编写属于你的jQuery插件
Writing Your Own jQuery Plugins
原文地址:http://blog.teamtreehouse.com/writing-your-own-jquery-plugins
jQuery是一个优秀的javascript库。它不但拥有良好的跨浏览器兼容性,容易学习掌握,还可以轻而易举的为你的网站添加有趣的交互。同时,大量的jQuery插件能够让你随心所欲的完成你想要完成的工作。
然而在平常的工作中,并不是总能够找到可以完全满足需求的插件,或者你想要将一些常用的功能封装以便保证项目的可重用性。在这些情形下,编写自己的jQuery插件是一个很好的满足需求的手段。
其实,编写jQuery插件并没有想像中难。这篇文章,我们将通过编写一个简单的插件,为其添加一些参数和事件回调,来向你完整的展示整个流程。
准备工作
像大多数编程指南的开篇一样,我们也以一个“Hello World”插件开始吧。在开始之前,先创建必要的文件并在HTML文档中引用它们。首先,在站点的js目录下新建插件文件jquery.hello-world.js。通常,jQuery插件的命名以“jquery.”开始。

接下来,需要在HTML文件中链接插件文件及其依赖的jquery核心库。我们将以下两行放置在文档的底部,也即</body>标签之前。
<script src="js/jquery-1.9.1.min.js"></script>
<script src="js/jquery.hello-world.js"></script>
jQuery插件的结构
jQuery本身已经为插件开发提供了足够的支持。但我们依然需要遵循JavaScript开发的最佳实践,将所有的代码都囊括在一个本地作用域中。下面是一个常规的jQuery插件基础结构:
(function($) {
$.fn.helloWorld = function() {
// Future home of "Hello, World!"
}
}(jQuery));
让我们花一点时间来理解一下上述代码的含义。通过将所有代码包含在 (function() {}) 自执行代码块中,能够保证插件内部的所有变量不会污染到全局变量。毕竟,我们肯定不愿意看到编写的插件和页面中的其它JavaScript代码发生冲突。
可能你已经注意到,我们定义插件的方式,就好像jQuery也位于其“无冲突”模式。再一次强调,我们需要避免插件与页面中其它JavaScript发生冲突,这也包括使用到的'$'符号。该符号很有可能被其它的JavaScript库使用。
最后,$.fn这种写法是jQuery定义插件的方式。这里将其命名为helloWorld并将所有代码放置在该函数中。下面,让我们做一些真正有意义的工作。
插件代码编写
为了使插件的代码尽可能的简单,同时又能达到演示的目的,我们将要完成的功能是改变关联的元素的文本内容为“hello world”。这已经近乎于傻瓜式的操作了。
(function($) {
$.fn.helloWorld = function() {
this.each( function() {
$(this).text("Hello, World!");
});
}
}(jQuery));
当在jQuery选择器上调用上述插件时,关联的元素已经是一个jQuery对象,因此不再需要再用"$(this)"结构进行包装。然而,如果需要在一个循环中使用每一个匹配的元素,比如$.each(),则一般会使用$(this)对循环的元素进行包装。
假如我们想要改变下面页面中所有的<h2>标题的文本:

调用的方式你已经很熟悉了,就像这样:
<script>
$(document).ready( function() {
$('h2').helloWorld();
});
</script>
结果为:

我们能做的远远不止如此。当上面的插件调用时,实际上完全被隔离在了它本身的作用域。也就是说,调用的作用链在插件内部被终止了。如果你试着以jQuery的链式写法调用其它操作时,是不会生效的。为了修复这个问题,需要确保返回每个DOM元素循环后的结果:
(function($) {
$.fn.helloWorld = function() {
return this.each( function() {
$(this).text("Hello, World!");
});
}
}(jQuery));
恭喜你,已经写出了你人生中的第一个jQuery插件!
稍安勿躁,好戏在后头!
现在你可能正沉浸在编写出自己的jQuery插件的喜悦中,这时候你的老大跑过来说,想要把现在的网站翻译成西班牙语。老天爷,现在该咋整?
其实,可以简单的添加一个参数完成上述需求。重新审视上述插件的代码,我们可以替换其内部的硬编码文本内容为一个变量,在调用的时候传入该变量的值。
(function($) {
$.fn.helloWorld = function( customText ) {
return this.each( function() {
$(this).text( customText );
});
}
}(jQuery));
如你所见,在调用的时候可以传入任何想要传入的文本值。办公室的马德里先生已经将我们需要的东西翻译成了西班牙语,现在可以使用参数的方式调用该插件:
<script>
$(document).ready( function() {
$('h2').helloWorld('¡Hola, mundo!');
});
</script>
页面呈现如下:

完全自由的控制
可能你已经感觉到一点担忧,如果在调用插件的时候没有传入文本怎么办?显而易见,页面中匹配的元素的文本会被插件修改为空值,这可能不是我们预期的结果。另外,我们的老大已经跑过来要求添加一个变量,如果他再跑过来要求添加更多的可定制化的选项怎么办?不断的添加参数毕竟不是长远之计,一劳永逸的解决方法是通过options对象。
我们已经知道具体的文本内容需要由外部传入,现在,老大又要求文本颜色和字体大小同样在调用时指定(好吧,我知道颜色和字体大小都可以通过jQuery内置的函数进行控制,这里仅仅是一个演示)。让我们为插件添加一个options参数对象,同时通过$.extend方法与默认的参数进行合并:
(function($) {
$.fn.helloWorld = function( options ) {
// Establish our default settings
var settings = $.extend({
text : 'Hello, World!',
color : null,
fontStyle : null
}, options);
return this.each( function() {
// We'll get back to this in a moment
});
}
}(jQuery));
现在我们有了可供外部设置的选项。如果调用的时候缺少了待替换的文本,将会使用指定的默认值。另外,在配置参数中添加了"color"和"fontStyle"两个属性,默认值均为"null"。如果在CSS文件中已经定义了颜色值和字体大小,在插件调用时不需要再重复指定。当然,二者均可以在插件内部重写。代码如下:
return this.each( function() {
$(this).text( settings.text );
if ( settings.color ) {
$(this).css( 'color', settings.color );
}
if ( settings.fontStyle ) {
$(this).css( 'font-style', settings.fontStyle );
}
});
因为该插件的目的是替换文本。如果提供的文本值为空则没有任何意义,这也是在插件内部为其指定默认值的原因,当参数缺失时显示缺省值总比空白要好得多。另一方面,颜色值和字体风格则只需要提供一个可供重写的入口。
这时候老大跑过来说想要将站点翻译为法语,另外还希望将文本颜色改为蓝色,字体调整为italic。幸运的是,我们的插件处理这些需求毫无压力:
$('h2').helloWorld({
text : 'Salut, le monde!',
color : '#005dff',
fontStyle : 'italic'
});

你看,我们的插件已经拥有了一些由外部控制的参数。将来可以在不影响现有调用的基础上,非常容易的添加或去掉某个参数。这些都益于良好的可扩展性。
但我们的老大带着另外一个需求再一次跑了过来:一旦插件按其预定的方式调用完毕,应该弹出一个对话框通知用户这个消息。为了达到这个目的,有两个选择:要么辞职,因为这个家伙明显无视最初的需求文档。要么不走这么极端的路线,为我们的插件添加处理回调函数的能力。
回调函数是JavaScript函数的参数,同时它本身也是一个JavaScript函数。其并不是jQuery独有的特性。初看上去回调函数是一个复杂的概念,但实际它的使用非常简单。
我们需要做的仅仅是在配置对象中附加一个额外的参数:
// Establish our default settings
var settings = $.extend({
text : 'Hello, World!',
color : null,
fontStyle : null,
complete : null
}, options);
现在,当插件调用完毕时,就该附加的“complete”参数生效了。为了调用该参数,首先需要确保其是一个真正的函数。幸运的是,jQuery已经内置了$.isFunction函数帮助我们完成这个检测:
return this.each( function() {
// Our plugin so far
if ( $.isFunction( settings.complete ) ) {
settings.complete.call( this );
}
});
页面中调用如下:
$('h2').helloWorld({
text : 'Salut, le monde!',
color : '#005dff',
fontStyle : 'italic',
complete : function() { alert( 'Done!' ) }
});
最终的效果,插件执行完毕后会触发回调函数:

结语
当你一遍又一遍的写着大量重复的JavaScript代码,自定义jQuery插件是一种很好摆脱这种泥沼的方式。通过自定义插件,你在保持自己代码DRY(dont repeat yourself)的同时,也确保了全局名称空间的独立和纯度。
如果你想调试上述示例代码,可以在我的 GitHub 获取。
(翻译)编写属于你的jQuery插件的更多相关文章
- 编写一个简单的Jquery插件
1.实现内容 定义一个简单的jquery插件,alert传递进来的参数 2.插件js文件(jquery.showplugin.js) (function ($) { //定义插件中的方法 var me ...
- 如何编写jQuery插件
要说jQuery 最成功的地方,我认为是它的可扩展性吸引了众多开发者为其开发插件,从而建立起了一个生态系统.这好比大公司们争相做平台一样,得平台者得天下.苹果,微软,谷歌等巨头,都有各自的平台及生态圈 ...
- 教你开发jQuery插件(转)
教你开发jQuery插件(转) 阅读目录 基本方法 支持链式调用 让插件接收参数 面向对象的插件开发 关于命名空间 关于变量定义及命名 压缩的好处 工具 GitHub Service Hook 原文: ...
- jQuery 插件编程精讲与技巧
适应的读者: 1.有一定的jquery编程基础但是想在技能上有所提升的人 2.前端开发的程序员 3.对编程感兴趣的学生 为什么要学习jquery插件的编写? 为什么要学习jquery插件的编写?相信这 ...
- 【转】教你开发jQuery插件
阅读目录 基本方法 支持链式调用 让插件接收参数 面向对象的插件开发 关于命名空间 关于变量定义及命名 压缩的好处 工具 GitHub Service Hook 原文:http://www.cnblo ...
- 开发JQuery插件(转)
教你开发jQuery插件(转) 阅读目录 基本方法 支持链式调用 让插件接收参数 面向对象的插件开发 关于命名空间 关于变量定义及命名 压缩的好处 工具 GitHub Service Hook 原 ...
- jquery插件与扩展一
要说jQuery 最成功的地方,我认为是它的可扩展性吸引了众多开发者为其开发插件,从而建立起了一个生态系统.这好比大公司们争相做平台一样,得平台者得天下.苹果,微软,谷歌等巨头,都有各自的平台及生态圈 ...
- jQuery插件手把手教会(一)
jQuery插件开发教程 ——让你的jQuery水平提升一个台阶 要说jQuery 最成功的地方,我认为是它的可扩展性吸引了众多开发者为其开发插件,从而建立起了一个生态系统.这好比大公司们争相做平台 ...
- 教你开发jQuery插件
jQuery插件开发模式 软件开发过程中是需要一定的设计模式来指导开发的,有了模式,我们就能更好地组织我们的代码,并且从这些前人总结出来的模式中学到很多好的实践. 根据<jQuery高级编程&g ...
随机推荐
- html2canvas插件对整个网页或者网页某一部分截图并保存为图片
html2canvas能够实现在用户浏览器端直接对整个或部分页面进行截屏.这个脚本将当前页面渲染成一个canvas图片,通过读取DOM并将不同的样式应用到这些元素上实现.它不需要来自服务器任何渲染,整 ...
- C# Retry重试操作解决方案(附源码)
一.前言 (1)对于Thread的Abort方法,如果线程当前正在执行的是一段非托管代码,那么CLR就不会抛出ThreadAbortException,只有当代码继续回到CLR中时,才会引发Threa ...
- Java中的受检异常
Java中的受检异常 Java提供了三种异常类型,受检异常(checked exception).运行时异常(runtime exception).错误(error).那么这受检异常在实际开发中又有什 ...
- 【腾讯Bugly干货分享】从0到1打造直播 App
本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/5811d42e7fd6ec467453bf58 作者:李智文 概要 分享内容: ...
- 作业三:PSP记录耗时情况
PSP2.1 Personal Software Process Stage Time planning 计划 15min Estimate 估计这个任务多久完成 130min Developing ...
- 探求网页同步提交、ajax和comet不为人知的秘密(上篇)
标题里的技术都是web开发里最常见的技术,但是我想这些常用的技术有很多细节是很多朋友不太清楚的,理解这些细节是我们深入掌握这些技术的一把钥匙,今天我就讲讲我使用这些技术时体会到的这些细节. 同步提交是 ...
- 【转载】学习资料存档:jQuery的deferred对象详解
我在以前的文章里提到promise和deferred,这两个东西其实是对回调函数的一种写法,javascript的难点之一是回调函数,但是我们要写出优秀的javascript代码又不得不灵活运用回调函 ...
- jQuery读取和设定KindEditor的值
在使用Kindeditor的时候,想要利用Ajax传值,但是通过editor封装的方法是行不通的,原因在于编辑器我们是放在另一个jsp页面,通过iframe来加载的,同时这个iframe的 ...
- 爱上MVC3~在控制器或Action上动态设定模板页(Layout)
回到目录 很多境况下,我们需要设置自己模块的layout,即它的布局页面,在MVC2中叫它模板页面,你可以在return view方法时设置它,当然,这不是一种好方法,因为我不想每个action都去设 ...
- 理解 Lua 的那些坑爹特性
按:最近看到了依云的文章,一方面,为Lua被人误解而感到十分难过,另一方面,也为我的好友, 依云没有能够体会到Lua的绝妙和优雅之处而感到很遗憾,因此我写了这篇文章,逐条款地说明了 依云理解中出现的一 ...