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插件的更多相关文章

  1. 编写一个简单的Jquery插件

    1.实现内容 定义一个简单的jquery插件,alert传递进来的参数 2.插件js文件(jquery.showplugin.js) (function ($) { //定义插件中的方法 var me ...

  2. 如何编写jQuery插件

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

  3. 教你开发jQuery插件(转)

    教你开发jQuery插件(转) 阅读目录 基本方法 支持链式调用 让插件接收参数 面向对象的插件开发 关于命名空间 关于变量定义及命名 压缩的好处 工具 GitHub Service Hook 原文: ...

  4. jQuery 插件编程精讲与技巧

    适应的读者: 1.有一定的jquery编程基础但是想在技能上有所提升的人 2.前端开发的程序员 3.对编程感兴趣的学生 为什么要学习jquery插件的编写? 为什么要学习jquery插件的编写?相信这 ...

  5. 【转】教你开发jQuery插件

    阅读目录 基本方法 支持链式调用 让插件接收参数 面向对象的插件开发 关于命名空间 关于变量定义及命名 压缩的好处 工具 GitHub Service Hook 原文:http://www.cnblo ...

  6. 开发JQuery插件(转)

    教你开发jQuery插件(转)   阅读目录 基本方法 支持链式调用 让插件接收参数 面向对象的插件开发 关于命名空间 关于变量定义及命名 压缩的好处 工具 GitHub Service Hook 原 ...

  7. jquery插件与扩展一

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

  8. jQuery插件手把手教会(一)

    jQuery插件开发教程  ——让你的jQuery水平提升一个台阶 要说jQuery 最成功的地方,我认为是它的可扩展性吸引了众多开发者为其开发插件,从而建立起了一个生态系统.这好比大公司们争相做平台 ...

  9. 教你开发jQuery插件

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

随机推荐

  1. Linux磁盘管理

    本系列的博客来自于:http://www.92csz.com/study/linux/ 在此,感谢原作者提供的入门知识 这个系列的博客的目的在于将比较常用的liunx命令从作者的文章中摘录下来,供自己 ...

  2. HTML5之Canvas时钟(网页效果--每日一更)

    今天,带来的是使用HTML5中Canvas标签实现的动态时钟效果. 话不多说,先看效果:亲,请点击这里 众所周知,Canvas标签是HTML5中的灵魂,HTML5 Canvas是屏幕上的一个由Java ...

  3. 我的ORM之十-- MyOql实现原理

    我的ORM索引 ORM的功能 两个基本功能 翻译:对象查询转化为SQL 映射:把查询结果转化为实体 更多功能 如果仅仅实现这两个功能,那这两个是可以独立的,实现起来也就很简单了.但MyOql的目标还有 ...

  4. DBCC CHECKDB

    DBCC CHECKDB 算是管理员们最常用的命令也是必须要知道的命令了.定期的检查及问题的修复都是比较重要的!!下面介绍一下 DBCC CHECKDB 的一些基本用法. DBCC CHECKDB 完 ...

  5. redis(二)高级用法

    redis(二)高级用法 事务 redis的事务是一组命令的集合.事务同命令一样都是redis的最小执行单元,一个事务中的命令要么执行要么都不执行. 首先需要multi命令来开始事务,用exec命令来 ...

  6. appserv中php升级问题

    当前版本为2.1,要升级到2.3.4 那么,首先到http://windows.php.net/downloads/releases/archives/ 找到2.3.4,需要注意的是,一般我们是非nt ...

  7. osgi 2

    基础的API BundleActivator  BundleContext ServiceReference HelloServiceFactory ServiceTracker osgi 疑惑: I ...

  8. svn add 添加到版本库

    转 svn add-添加到版本库 常用操作1.添加一个文件到工作拷贝:$ svn add foo.c 2.当添加一个目录,svn add缺省的行为方式是递归的:$ svn add testdir 3. ...

  9. javascript日常总结

    如何去除掉inline-block元素之间的默认间距 前几天写一个页面 1 2 3 4 div{width:900px;} div li{ display:inline-block; width:30 ...

  10. JavaScript练习之for循环语句

    for循环四要素:初始条件.循环条件.循环体.状态改变. 1.for(var a=i;i<=aa;i++) { 循环体(例sum=sum+i  sum是输出的) } 例题 1-20关没关一分 2 ...