扩展 jQuery

978-7-115-36354-1
作者: 【美】Keith Wood
译者: 李强
编辑: 傅道坤

图书目录:

详情

本书讨论了如何构建jQuery库的自定义扩展。它提供了如何编写插件的详细指导和相关技巧,帮助读者充分利用iQuery内部的所有扩展点。读者将学习到如何为了最大程度的复用来设计插件,同时也将学习到如何编写新的小部件和jQuery UI特效。他们还将探索关键领域的扩展,如Ajax、事件、动画和验证。

图书摘要

版权信息

书名:扩展 jQuery

ISBN:978-7-115-36354-1

本书由人民邮电出版社发行数字版。版权所有,侵权必究。

您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。

我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。

如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。

• 著    [美] Keith Wood

  译    李 强

  责任编辑 傅道坤

• 人民邮电出版社出版发行  北京市丰台区成寿寺路11号

  邮编 100164  电子邮件 315@ptpress.com.cn

  网址 http://www.ptpress.com.cn

• 读者服务热线:(010)81055410

  反盗版热线:(010)81055315


jQuery是当今应用最为广泛的一个JavaScript框架。它简化了HTML文件的遍历、事件处理、动画、Ajax互动等操作,从而使开发人员可以更加容易、便捷地开发出强大的静态和动态网页。

本书分为4部分,共14章,讲解了为jQuery库创建自定义扩展的方法,从最大可重用性的角度来设计和编写插件的方法,以及为jQuery UI编写小部件和特效的方法。此外,本书还讲解了另外一些关键主题,如Ajax、事件处理、动画和Validation插件等的扩展。

本书适合具有一定jQuery和JavaScript知识的前端开发人员阅读。


我在2007年初第一次接触jQuery,就立即发现它的直观和简单易用。我能快速地选择元素,并显示和隐藏它们。接下来我试着使用了一些第三方插件,但是发现它们的实用性和可用性都相差很大。

幸运的是,我最初写的插件成为了jQuery社区的一个主要插件。当时我偶然间看到了Marc Grabanski的Clean Calendar插件(他已经把它转为了一个jQuery插件),我喜欢它提供的日期输入界面,于是就开始研究它,并添加更多功能,作为探索jQuery能力的一个途径。最终我把这些提供给了Marc。从此,我们开始了接下来几年在这个插件上的合作。

后来,这个Calendar插件被重命名为Datepicker插件,jQuery UI团队也选择将其作为他们的日期选择插件的基础。

自那时开始,我一直出于需要和兴趣开发其他一些插件。最流行的一些包括另一个允许选择日期范围或多个独立日期的Datepicker、一个提供非公历日期的Calendars插件、一个显示到达给定时间所剩余时间的Countdown插件,以及一个允许用户和页面上SVG元素交互的SVG Integration插件。这段时间,我学习了许多关于JavaScript和jQuery的知识,以及如何为jQuery编写插件。

创建插件是重用功能的一个理想方式,能使其简单地被纳入其他网页。它还可以让开发者更彻底地测试代码,确保在所有使用环境中的行为一致性。

这几年间,jQuery在功能和大小上都显著增长,但是它让开发者的工作更为简单的目的并没有改变。欣欣向荣的插件社区证明了jQuery团队提供这个易于扩展的平台的远见。我希望本书中提供的见解能让读者在自己的项目中最大化地使用jQuery的功能。


jQuery是Web上使用最广泛的JavaScript库。它提供了许多功能,使得Web开发更加容易。但是它只专注于提供广泛适用和使用的功能,并不能做开发者希望的所有事情。开发者可以为每个网页编写代码实现自已的需求,但是如果发现在多个页面间有重复代码,就是时候创建一个jQuery的插件了。

一个插件允许开发者把代码打包在一个可重用的模块中,它可以被很容易地应用在其他网页上。开发者可以受益于只需一份代码库,这样不仅可以降低测试和维护代价,也能使整个网站有一致的外观和行为。

设计jQuery的目的是适应这些插件,允许它们成为jQuery环境的一级成员,并可以与内置的功能一起使用。本书介绍如何使用最佳实践原理来创建一个jQuery插件,使其在不干扰其他插件的情况下与jQuery集成,并且提供了一个灵活和健壮的解决方案。

这是一本关于扩展jQuery来创建可重用插件的书。读者可以是那些想知道jQuery的扩展点,在他们的项目中创建可重用模块的技术主管,也可以是那些想了解jQuery背后如何书写健壮代码细节的网页开发者,还可以是那些想要为jQuery社区创建一个最佳实践的插件的第三方插件开发者。

这里假定目标读者熟悉jQuery。他应该可以使用jQuery来选择元素,然后操作这些元素来改变属性,显示或隐藏元素,或者附加事件处理器;也应该熟悉使用已有的第三方插件为自已的页面添加功能。

关于jQuery本身的介绍,请参考Bear Bibeault和Yehuda Katz的jQuery in Action,Second Edition(Manning,2010)。

jQuery是一个JavaScript库,所以开发者也应该熟悉JavaScript语言。大多数插件代码都是直接的JavaScript和一些jQuery调用或者集成点。代码中经常用到匿名函数、三元运算符和闭包结构。读者如果已经知道这些术语是最好不过,否则需要先温习一下JavaScript。

为了更深入地了解JavaScript语言,请参考John Resig和Bear Bibeault的Secrets of the JavaScript Ninja(Manning,2012)。

本书分为4部分。第1部分(第1~3章)包括提高jQuery体验的简单扩展。第2部分(第4~7章)介绍了插件和函数的最佳实现方法。第3部分(第8~10章)专注于扩展jQuery UI来提升页面。第4部分(第11~14章)涵盖了其余部分,包括动画、Ajax、事件处理,以及Validation插件,这些不是jQuery的一部分,但是却扮演了重要的角色。

jQuery和jQuery UI都是MIT许可证下的开源库。它们可以分别从相应的网站直接下载:http://jquery.com/http://jqueryui.com/

本书中所有的示例源代码都可以从Manning网站上的本书页面中找到:http://www.manning.com/ExtendingjQuery

 Massachusetts Institute of Technology license agreement,https://github.com/ jquery/jquery/blob/master/ MIThttp://write.epubit.com.cn/article/edit/5833#aca01-LICENSE.txt。


本书的封面插图名是“Dolenka”,表示一位从斯洛文尼亚和匈牙利边界上的村庄Dolenci来的妇女。该插画取自克罗地亚斯普利特民族博物馆2008年出版的Balthasar Hacquet的《图说西南及东汪达尔人、伊利里亚人和斯拉夫人》(Images and Descriptions of Southwestern and Eastern Wenda, Illyrians, and Slavs)的最新重印版。Hacquet(1739~1815)是一名奥地利内科医生及科学家。他花费数年时间去研究各地的植物、地质和人种,这些地方包括奥匈帝国的多个地区,以及许多部落和民族居住过的威尼托、尤里安阿尔卑斯山脉及西巴尔干等地区。Hacquet发表的很多论文和书籍中都有手绘插图。

Hacquet的出版物中丰富多样的插图生动地讲述了阿尔卑斯山和巴尔干地区200年前的独特个性。在那时,着装风格就可以区分相隔几英里的两个村庄的人们,通过服装,人们能轻易地分辨不同人的民族部落、社会阶层,以及从事的行业。从那以后,服装风格发生了改变,丰富的地区多样性开始淡化。现在,通常很难说一个洲的居民和其他洲的居民有什么不同,今天的意大利阿尔卑斯山风景如画的城镇和村庄的居民已经很难轻易地与欧洲其他地方的居民进行区分。

我们在Manning通过图书封面让这些两个世纪前的服装重现于世,并借此来颂扬计算机行业的创意、进取和乐趣。

 1英里≈1.609千米。——译者注


Keith Wood有30多年的开发经验,他从2007年初开始对jQuery作出贡献。他已经写了20多个插件,包括最初的Dorld Calendar和Datepicker、Countdown和SVG,并且把它们发布到gjQuery社区。他也经常在jQuery论坛上回答问题,并且成为2012年前五名的贡献者。

在日常工作中,他是一个网站开发者,使用Java/J2EE开发后端,以及使用jQuery开发前端。他生活在澳大利悉尼,与他的搭档Trecialee一起利用业余时间写作了本书。


李强,架构师,现就职于道富银行技术中心,从事金融软件架构设计工作,参与开发了多个大型金融项目。他还是《HTML5+JavaScript动画基础》一书的译者。读者可以通过sparkli@hotmail.com与他联系。


jQuery是如今Web上使用最为广泛的JavaScript库,全世界一半以上的网站都在使用它。它提供了跨浏览器的支持,可以让开发者不必纠结于特定浏览器的细节差异。jQuery的语法简洁,其独特的选择器、链式调用、事件机制、对Ajax的支持都可以让开发者用很少的代码实现自己的需求。最重要的是,它本身还提供了强大的扩展点,从而使得它有了无限的扩展可能性。简言之,只有想不到,没有做不到。

本书适用于有一定jQuery使用基础,并想进一步在jQuery上开发自己的扩展功能的读者。如果读者没有jQuery基础,也没有关系,可以边读边学,但是至少需要熟悉JavaScript语言。如果读者连JavaScript语言都不熟悉,建议先读一本JavaScript的入门书籍,再来阅读本书。

本书着重介绍jQuery的扩展点,几乎覆盖了每一个方面,主要分为4大部分。

第1部分介绍了简单的扩展,包括简单的插件、选择器和过滤器的扩展。

第2部分介绍了插件和函数,包括插件的基本开发原则、集合插件、函数插件,以及如何为插件进行测试、打包和书写文档。

第3部分介绍了扩展jQuery UI,包括jQuery UI小部件框架、鼠标交互,以及特效。

第4部分介绍了jQuery的其他扩展,包括复杂属性的动画、Ajax的扩展、事件的扩展,以及验证规则的扩展。

本书的作者Keith Wood是一位在jQuery社区中极有声望的开发者,jQuery中的Datepicker插件就是他的作品。他在本书中深入地介绍了每一个扩展点,并且给出了详细的示例。非常感谢他为读者带来了这样一本好书,也非常感谢他能在我翻译本书的过程中抽出宝贵时间为我解释一些疑惑和难点。

我要感谢我的妻子。翻译本书时,我花费了大量的时间,因而没能好好陪她。特别要感谢我的搭档朱悦倩,她校对了全书的初稿,修正了许多错误,并提出了宝贵的修改意见。正是她细腻的性格、对语言的独特感悟以及认真负责的态度,使得本书的质量大幅提高。尽管我们在翻译的过程中谨小慎微,但仍然难免会有一些疏漏。如果读者发现了任何错误或不足,请不吝指教。

李强

2014年7月于杭州


自从2006年jQuery首次亮相以来,它已发展成管理和增强HTML文档的最流行的JavaScript库。jQuery的跨浏览器设计允许开发者专注于网站建设,而不必纠结于浏览器特性。到2013年,排名前100万(访问量)的网站中,超过一半使用了jQuery。同样,构建在jQuery上的jQuery UI库也是最受欢迎的UI小部件。

它之所以如此流行,一个原因是jQuery团队不断添加功能,所以几乎开发者遇到的任何问题都可以用jQuery方法来解决。然而,每一个添加到jQuery核心代码中的功能,都意味着无论网站有没有用到这个功能,访问者都需要下载更多的JavaScript字节。这样一个庞大的整体库为开发带来了方便,但是却降低了性能,因而并不是一个好的权衡。

为了应对代码膨胀的危害,jQuery只是把最为常用的功能包括在库中,并提供一个可供开发者扩展的基础。经过多年的发展,jQuery插件已经形成了一个令人难以置信的生态系统。它的驱动力来自于每个开发者解决特定问题的需求,以及他们在广泛的jQuery社区中慷慨分享的代码。jQuery的成功很大程度上归功于这种精神,以及团队通过类似于plugins.jquery.com这样的网站对这种精神的促进。

Keith Wood很适合通过本书作为读者的向导。他是jQuery论坛的常客,并在很多年里都是最佳贡献者,为解决开发者遇到的实际问题提供了许多高质量的回答。他也通过开发许多流行的jQuery插件获得了自己的威望。Keith有着对jQuery扩展的专业理解和作为导师的直觉,他知道哪些jQuery话题需要深入的解释,而不是泛泛而谈即可。

本书深入研究了jQuery功能扩展的几乎每一个方面——无论是基于个人需求还是出于职业目的。最为常见的扩展类型是扩展jQuery Core方法的基础jQuery插件,但是本书用同样的篇幅介绍了基于jQuery UI小部件的插件,它们通常为可视化的扩展提供更好的基础。关于jQuery UI小部件的详细文档非常稀缺,因而这些章节就显得尤为珍贵。

我特别高兴的是,Keith在单元测试的话题上投入了一些时间。有一套全面的单元测试似乎是不必要的额外工作,但是几个月后,一个插件的一个正常变化会导致整个网络团队在线上进行数小时的调试,同时涌入大量用户投诉,读者才会发现单元测试的价值。单元测试并不能找出所有错误,但是它们扮演完整检查的角色,防止一些不耐烦的开发者在做手动回归测试时,所造成的一些遗漏。

无论读者学习jQuery扩展的动机是什么,请考虑为开源社区贡献一份力量,让其他人也能从中受益。这契合了jQuery的哲学。与其他人分享自己的知识不仅能帮助他人,同时也能提升自己的专业认可度。

Dave Methvin

JQuery基金会总裁


我首先感谢John Resig和jQuery团队为全世界的Web开发人员提供了这样一个有用的工具。

我还要感谢Marc Grabanski允许我为Calendar/Datepicker作出贡献,由此开启了我开发插件的生涯。

写一本书总是一个团队的努力。我要感谢Manning的编辑团队:Bert Bates、Frank Pohlmann和Cynthia Kane,技术校对团队:RensoHollhumer和MichielTrimpe,以及整个制作团队的支持和指导。特别感谢Manning的Christina Rudloff,是他最初打算做一本jQuery UI书的想法促成了本书的问世。

感谢多年来联系我并为我提供意见、建议、错误,以及将我的插件进行本地化的开发者,特别是那些做出贡献的开发人员。

感谢对本书早期版本的书稿提供了意见,并由此提高了最终产品质量的审阅者:AmandeepJaswal、Anne Epstein、BradyKelly、Bruno Figueiredo、Daniele Midi、David Walker、EcilTeodoro、Geraint Williams、Giuseppe De Marco、PhD、Jorge Ezequiel Bo、Lisa Z. Morgan、Mike Ma、Pim Van Heuven和Stephen Rice。

特别感谢jQuery基金会总裁Dave Methvin为本书作序并称赞本书。

最后,要重点感谢我的搭档Trecialee。读者所看到的内容很多都是她贡献给这个项目的(尽管她不懂本书的内容)。


jQuery是如今网络上使用最广泛的JavaScript库,它提供的许多功能使前端开发人员的工作变得简单。开发者可以通过扩展jQuery来提供一些可重用的附加功能,使它变得更加强大。

第1章首先简要地介绍了jQuery的历史,然后讲解开发者可以在哪些方面扩展jQuery,最后通过一些现有的jQuery插件来展示扩展的可能性。

第2章更为详细地介绍了jQuery的架构以及可能的扩展点。然后,为了让读者快速上手,介绍了如何开发一个可以马上使用的简单插件。

最简单的扩展就是增强jQuery的选择器——可以用来选择元素的一个字符串。第3章将会通过许多例子来介绍如何创建自己的选择器。


本章涵盖以下内容:

jQuery是一个可以使得与网页上元素交互更容易的JavaScript库。它通常被用于通过直接选择或者遍历DOM来查找元素,然后在这些元素上应用一些功能。开发者可以添加或删除这些元素,或者改变它们的属性,还可以为它们添加事件处理器用来响应用户的动作。开发者也可以随着时间推移改变元素的属性来产生动画。jQuery也提供了Ajax让开发者容易地从服务器上获取数据,并且不阻塞当前页面及其内容。

上一章中提到过jQuery不是万能的,所以它提供了许多扩展点或集成点,从而培育了一个欣欣向荣的第三方插件社区。

本章着眼于jQuery的架构,它允许插件与内置的代码一起工作。然后通过介绍一个简单的集合插件(可以操作一组元素)来说明可以做些什么。以后章节将详细介绍每一个扩展点,以及如何使用它们来提升jQuery的能力,并且提出了一套插件开发的指导原则和最佳实践。

jQuery的源代码由许多文件组成,这是为了开发阶段的需要。在构建阶段,它们将会被合并为单个JavaScript文件(供产品使用的最小化版本,或者方便调试的完整版本)。每一个源代码文件专注于jQuery的一个特定功能,其中许多提供了扩展点,可以用来增强内置功能。

一个扩展点是指一个可以用来注册特定类型(如集合函数或者 Ajax 增强)新功能的jQuery属性或者函数,这些新功能被视为和相应的内置功能完全一样。当框架处理到开发者的插件的引用时,就会调用相应的插件代码。

图2.1反映了组成jQuery的模块或文件,以及它们之间的依赖。

图2.1 jQuery的模块、依赖关系和扩展点

jQuery的主要可扩展模块(图2.1中的阴影部分)包括:提供了选择DOM元素功能的Sizzle库;包括jQuery函数本身的core模块、处理Ajax的ajax模块、处理事件的event模块,以及提供动画功能的effects模块。

表2.1列出了jQuery和jQuery UI所提供的扩展点,接下来的几小节中会介绍它们。回想一下,$是函数jQuery的一个别名(除非通过调用noConflict释放$)。

表2.1 jQuery的扩展点

扩 展 点

目 的

示 例

参 见

$

工具函数

$.trim
$.parseXML

第6章

$.ajaxPrefilter

Ajax预过滤器

$.ajaxPrefilter('script',...)

第12章

$.ajaxSetup

Ajax 数据类型转换器

$.ajaxSetup({converters:
{'text xml',$.parseXML}})

第12章

$.ajaxTransport

Ajax传输机制

$.ajaxTransport('script',...)

第12章

$.easing

缓动动画

$.easing.swing
$.easing.easeOutBounce

第10章

$.effects

jQuery UI 视觉效果(jQueryUI 1.8-)

$.effects.clip
$.effects.highlight

第10章

$.effects.effect

jQuery UI 视觉效果(jQueryUI 1.9+)

$.effects.effect.clip $.effects.effect.highlight

第10章

$.event.special

自定义事件

$.event.special.mouseenter $.event.special.submit

第13章

$.expr.filters $.expr[':'] $.expr.setFilters

选择器(jQuery 1.7-)

$.expr.filters.hidden $.expr.setFilters.odd

第3章

$.expr.pseudos $.expr[':'] $.expr.setFilters

选择器(jQuery 1.8-)

$.expr.pseudos.enabled $.expr.setFilters.first

第3章

$.fn

集合插件

$.fn.show
$.fn.append

第5章

$.fx.step

属性动画(jQuery 1.7-)

$.fx.step.opacity

第11章

$.Tween.propHooks

属性动画(jQuery 1.8-)

$.Tween.propHooks
.scrollTop

第11章

$.validator.addMethod

验证插件规则

$.validator.add Method
('USPhone', ..., ...)

第14章

$.widget

jQuery UI小部件

$.widget('ui.tabs', ...)

第8章、第9章

jQuery将Sizzle选择引擎作为它自己代码的一部分。这个独立的库用来执行选择处理,让开发者在网页上定位到自己需要的元素。在可能的情况下,它会把操作代理到浏览器提供的本地函数上以提高性能,其余部分直接由JavaScript实现。例如,开发者想在ID为preferences的元素中,找到所有跟在input字段(也可能是checkbox的标签)后的label元素,就可以使用如下代码:

Sizzle允许开发者通过节点名、类名、子节点或属性值来选择元素。开发者也可以使用各种伪类选择器,包括层叠样式表(CSS)规范定义的和 Sizzle 自己添加的,例如:checked,:even和:not。通过把多个选择器组合在一个选择字符串中,开发者可以找到想要的元素。

伪类选择器


CSS规范:“伪类基于特征对元素进行分类,而不是基于它们的名字、属性或者内容;原则上,特征是不可以从文档树上推导得到的。”这些选择器都通过一个冒号(:)后面跟着位置条件(如:nth-child(n))、内容条件(:empty)和否定条件(:not(selector))进行区分。

开发者可以通过扩展$.expr.pseudos(jQuery 1.8之前的版本中是$.expr.filters)添加自己的伪类选择器,并在选择过程中使用。最后要说的是,一个选择器只不过是一个函数,它接收一个元素作为参数,如果这个元素被接受,则返回true,被拒绝,则返回false。

通过扩展$.expr.setFilters,开发者可以在当前的一组匹配元素中,通过位置进行过滤元素。开发者需要提供一个函数,它返回匹配到的元素集合(jQuery 1.8之后版本)或返回一个布尔标志来标识是否包含(jQuery 1.7及之前版本)。

关于如何为jQuery/Sizzle添加自定义选择器和过滤器的详细内容,请参见第3章。

集合插件是最为常用的jQuery扩展,被用来操作使用选择器或者遍历DOM得到的一组元素。

这些插件必须扩展$.fn,用一个函数来实现自己的功能。这样,它们就能被整合到jQuery内置的处理流程中。如果读者看一下源码,会发现$.fn只是$prototype的别名。这就意味着,任何加入$.fn的函数对所有jQuery集合对象都是可用的,例如使用选择器或者DOM元素调用jQuery得到的结果。这样,这些函数就能在恰当的上下文中在这些集合上调用。

所有集合插件都应该返回当前元素集合,或者当它提供了某种形式的遍历功能时,也可以返回一个新集合。这样,它们就能与其他jQuery函数一起链式调用——jQuery操作的一个核心范式。

第4章将介绍一系列包括最佳实践的原则。第5章则介绍一个实现了这些最佳实现的插件开发框架。

可以通过直接扩展$把那些不能操作元素集合的JavaScript函数(例如内置的trim和parseXML)添加到jQuery中。虽然不是必须把它们包括到jQuery中来(它们也可以被定义为独立的JavaScript函数),但这样它们可以充分利用jQuery的其他功能,并且保证使用风格的统一。另外,把它们加进来也减轻了全局命名空间的混乱,降低了命名冲突的可能性,同时也保证功能相关的函数能放在一起。

工具函数没有固定的参数列表,但是它们可以接收需要的任何参数。

第6章将介绍如何为jQuery添加新的工具函数。

jQuery UI是官方提供的一组构建在基本jQuery库之上的UI组件、行为和特效。它提供了一个实现最佳实践原则的小部件开发框架。

通过调用jQuery UI的$.widget函数可以创建小部件。这个函数的第一个参数是新的小部件的名字(包括命名空间来防止名字冲突);第二个参数是可选的,用来指定继承的基“类”;第三个参数是一组自定义函数和覆盖,用来增强基本的功能。小部件框架会负责把小部件应用在选择好的元素上,并设置、获取和保存控制小部件外观和行为的选项,还有当小部件不再需要时的清理工作。函数$.widget
.bridge在幕后维护用户调用的集合函数与定义小部件时提供的功能之间的映射。

第 8 章将进一步详述 jQuery UI 小部件和它提供的框架。第 9 章将探讨如何使用jQuery UI的鼠标模块来实现一个围绕鼠标拖动功能的新组件。

jQuery UI 另一个主要部分是网页元素的一系列动画特效。这些动画大多数用来隐藏和显现一个元素,比如blind(百叶窗)和drop(掉落);还有一部分用来吸引用户的注意,比如highlight(高亮)和shake(晃动)。

可以通过扩展$.effects.effect(jQuery 1.9之前的版本中是$.effects)把新的特效整合到jQuery UI的特效处理中,然后这些特效就可以在jQuery UI提供的effect函数或者show、hide、toggle 这些增强函数中使用了。每个特效都是一个函数。它把一个回调函数添加到当前元素的 fx 队列中,前一个入队的事件处理完毕后,这个回调函数会执行特效的动画。

缓动(Easings)定义了一个属性值如何随着时间变化,可以被用在动画中控制加速和减速。缓动虽然是jQuery基本的一部分, 但只提供了两个实例—linear(线性)和swing(摇摆)。 jQuery UI则提供了30种额外的缓动。开发者可以通过扩展$.easing添加自己的缓动,需要定义一个函数来返回动画过程中当前时间间隔(通常是0到1)的属性变化值(通常也是0到1)。

想得到更多关于jQuery UI特效的信息,以及关于缓动的介绍,请参见第10章。

jQuery的动画功能允许开发者改变一个选定元素的多个属性值。这些属性通常会影响元素的外观,或者移动元素的位置,改变元素大小或边框尺寸,或者调整它内容字体的大小。不过jQuery只能在数值类型的属性(包括一个单位)上进行动画。开发者需要添加自定义动画来支持更加复杂的属性。

通过扩展$.Tween.prop-Hooks来实现在其他属性上的动画,开发者需要提供两个函数,一个获取属性值,另一个设置属性值。在jQuery 1.8 之前的版本中,开发者需要扩展$.fx.step,并提供一个函数来执行动画的一帧。

第11章将介绍如何为jQuery添加一个新的动画。

Ajax处理是jQuery所提供的功能中的一个关键部分。它可以更容易地从服务器获取信息并更新当前页面,而且不用刷新整个页面。因为获取的数据可能有多种格式,jQuery使用预过滤器(prefilter)控制开始读取数据之前的处理,使用传输器(transport)获取基本的数据,使用转换器(converter)把数据转换为一个可用的格式。这些机制都可以被增强,以满足特殊需求。图2.2是一个标准的Ajax调用成功的时序图。

图2.2 Ajax时序图,标出了扩展点

通过调用$.ajaxPrefilter 函数,开发者可以定义一个在请求某个特定格式的数据(比如html、xml 或者 script)时被调用的函数。因为开发者的函数持有一个用来获取数据的XMLHttpRequest对象引用,所以开发者可以完全控制每个请求,包括取消请求。

开发者可以通过调用$.ajaxTransport函数为特定数据格式定义一个处理函数,处理真正获取数据的过程,这样开发者可以自定义如何访问数据(比如把图像数据直接加载到Image元素中)。默认使用XMLHttpRequest对象。

最终,数据通常以文本格式返回,但是在做一些初始化处理后可能会更有用,比如把XML解析为DOM。通过调用$.ajaxSetup函数,开发者可以定义新的转换器把结果转换为另一种格式,并作为Ajax请求的结果返回。

关于如何通过定义自己的预过滤器、传输协议以及转换器,请参见第12章。

jQuery允许开发者为选出的元素附加事件处理器,以响应用户动作。在发生基本的鼠标、键盘及状态变化的事件时,这些处理器会被调用。如果有必要,开发者可以定义一个自定义事件来处理特殊的场景。

开发者可以通过扩展$.event.special添加一个自定义事件。每一个事件的定义都提供这一事件的类型,以及设置事件处理的函数,当这个事件不再需要时的卸载函数,以及在适当情况下触发事件的函数。

第13章将详细介绍如何创建和处理自定义事件。

尽管验证插件不是基本 jQuery 库的一部分,但是它是一个应用非常广泛的插件,并且提供了扩展点,允许开发者添加新的验证规则。这些规则可以和内置的那些规则(如required和number)一起使用,在提交表单前确保字段中填写的数据的完整性和正确性。

开发者可以调用$.validator.addMethod来定义一个自定义验证规则,开发者需要提供规则的名称和一个验证函数,如果验证成功,则返回true,否则返回false。此时还需要指定一个验证失败时的错误信息。开发者可以用$.validator.addClassRules函数使自己的新规则做到在元素的class属性中指定名字就能自动验证。

第14章将介绍如何定义开发者自己的验证规则。

jQuery插件简直可以做任何事情,大量的第三方插件就可以证明这一点。从影响单个元素的简单插件,到改变多个元素的外观和行为的复杂插件,比如验证插件,应有尽有。

最为常用的一类jQuery插件是集合插件,它被用来为使用选择器或者遍历DOM得到的一组元素添加功能。开发者可以创建一个水印插件作为这种类型的插件的一个简单示例,它在必要时为字段内部提供一个标签。这会让开发者对如何构建一个插件有一定的感知。

为了节省表单所占用的空间,有时开发者会省略字段的标签,并用一个占位符(字段内的一段文字,在开始输入时隐去)来代替。当字段为空时,占位符则显示出来。为了保证更好的用户体验,占位文字通常为灰色,以表示这不是字段的真实值。这个标签功能通常被称为水印(watermark)。

可以在插件初始化时指定占位文字,但是更好的方式是在每个字段上指定这个文本。这样可以一次设置多个字段,并且每个字段都有自己的标签。Input字段的title属性是存放这个占位文字的理想之处,它的目的是保存这个字段的简短描述,当鼠标悬浮在字段上时会显示在一个提示框(Tooltip)中。对于有视觉障碍的人,title可以在字段获得焦点的时候被读出来,用来识别该字段。

当字段获取焦点时,如果存在占位文字,则需要把它移除,并更改字段的样式以清除灰色字体。类似地,当字段失去焦点时,如果字段还是空,开发者需要恢复占位字符和样式。图2.3显示了水印插件在输入数据的不同时期的运行状态。

图2.3 运行中的水印插件:输入前、输入名字后、准备提交

为了获取最大的灵活性,显示占位文字时字段的样式应该由CSS控制。开发者可以在字段显示占位符时为它指定一个类(class),并在它失去焦点或输入一个真实值时移除这个类。实际的外观则由一个CSS样式控制,并且可以很容易地由用户覆盖。

因为Watermark插件可以应用在页面的多个元素上,所以它是一个集合插件。这意味着它的操作对象是通过选择器或者遍历DOM得到的一组元素。这样,它就需要扩展$.fn来把自己的功能整合到jQuery的选择和调用流程中。

程序清单2.1是Watermark插件的完整代码。

程序清单2.1 Watermark插件

这个插件通过声明$.fn.watermark 1 来扩展$.fn,使它能与jQuery的选择和操作流程融为一体。新定义的这个属性(watermark)以它所提供的功能命名,将来也用这个名字来访问。这个属性的值是一个函数,它接收一个参数(options)并为目标字段添加新功能。它只用到了一个选项,就是当一个字段显示占位文字时的样式类名。开发者需要为这个选项提供一个默认值,但是同时允许用户覆盖它2。首先,开发者需要把这个默认值定义为一个对象,属性为watermark Class,值为watermark。这个对象可以被用户提供的任何选项所扩展,从而可能导致默认值被覆盖。||{}结构保证了当用户在初始化时没有提供参数的情况下,把options替换为一个空对象(不改变默认值)。

作为jQuery哲学的一个重要组成部分,为了使这个插件支持与其他插件的链式调用,这个函数必须返回它正在操作的元素集合3。因为大多数内置的jQuery函数也返回这个集合,开发者可以返回调用标准jQuery功能的返回结果。

开发者需要为每个选定的字段添加一个focus处理器3。在这个处理器中,因为当前字段需要被用到多次,所以被保存为一个jQuery对象的引用。接下来,开发者检查当前字段的值是否等于字段的title属性的值4。如果是,则通过把字段值设置为空来移除占位文字5,并移除选项中指定的标记类。

因为开发者在同样的字段上执行同样的操作,可以再接一个blur处理函数6。再次保存一个当前字段的引用,以便重用。这次如果当前字段值为空7 ,则恢复占位文字(从title属性获取)和标记类8

最后,触发刚刚定义的blur处理函数来根据字段的当前值进行初始化9

因为占位文字设置为每个字段的值,若不做些处理,它将被提交到服务器。使用占位符是一个纯粹的用户界面行为,所以也应该在客户端提交表单之前清除这些值。

清除这些占位符的一个简单方法是定义另一个集合插件来完成这个任务。程序清单2.2中的代码就是这个另外的函数。

程序清单2.2 清除水印

因为开发者操作的仍然是页面上的一组元素,所以再次通过扩展$.fn来定义插件函数$.fn.clear-Watermark1。使用each函数返回当前选定集合的引用,以便链式调用2。对于每一个选定的元素,如果它的当前值与字段的title属性相同3,则重置它4

开发者可以在把这些字段值提交到服务器或者做其他处理之前调用这个函数。开发者可以在必要的时候通过在每个字段上触发blur处理函数来轻易地恢复占位文字。

直接把前面的代码放在需要的页面上,就能使用这个水印插件。还可以把代码放到一个单独的JavaScript文件(jquery.watermark.js)中,并把它加载到开发者的页面中。类似地,插件的样式也可以直接放在页面上,或者从一个单独的CSS文件(jquery.watemark.css)加载。把样式和代码放在单独的文件中有利于在其他页面上进行重用。

图2.4展示了一个使用水印插件的页面。程序清单2.3是这个页面的代码。

图2.4 使用水印插件的简单页面

程序清单2.3 使用水印插件

首先为水印插件加载包含样式的CSS文件1。这个样式使占位文字显示为灰色(假定使用默认的标记类):

首先必须加载jQuery库2,以保证后续的插件代码可以使用它3。当DOM被加载完毕并一切就绪时4,开发者就可以使用这个新插件了。

通过在选定的字段(包含wmark类的input字段)上调用插件函数,开发者可以应用插件的功能5。回想一下,这个插件返回之前选定的元素集合,这样后续的操作就可以进行链式调用。因为这些字段被初始化为空,所以插件会读取每个字段的title属性,并把它作为占位文字填充字段。

在这些字段被提交并做进一步处理时6,开发者首先需要在使用这些字段值前把字段的占位文字清除7。根据流程,开发者可以通过在受影响的字段上触发blur处理函数来恢复占位文字8

可以在文档的body中找到使用水印插件的实际字段9,它们被设置了wmark类以便选择。

当开发者在浏览器中打开这个页面时,会发现一开始两个输入框都有灰色的占位文字。当把焦点移动到其中一个字段上时,占位符会消失,并且开发者可以输入合适的值。如果开发者没有输入任何值,当焦点离去时,占位文字又会恢复回来并且字段会被灰掉。当单击提交按钮时,所有的占位文字都会被移除,字段值会被显示在提示框中,并且如果有必要的话,占位文字会被恢复。

这个简单的集合插件让读者领略了一个jQuery插件用寥寥几行代码能实现什么功能。通过把代码放在一个单独的文件中,开发者可以轻松地在其他需要同样功能的页面上重用它。接下来的几章将介绍一些开发者需要努力应用在自己的插件上的最佳实践原则,使自己的插件的功能更加强大和健壮。读者还可以看到两个为常见的控件需求提供基础设施的控件框架,以及如何测试、打包和用文档说明自己的插件,以便其他人能更好地使用。

开发者需要知道


jQuery被设计为可扩展的。

jQuery有许多扩展点,允许开发者为它添加不同类型的功能。

创建一个简单的插件很容易。

通过扩展$.fn可以添加一个可以操作一组选定元素的集合插件。

把开发者的插件代码放在单独的文件中,以便在其他页面上重用。

自己试试看


修改水印插件,从data-label属性中获取占位文字。这样就可以在提供一个占位文本的同时,还可以用title属性表达更长的提示信息。

jQuery的开发者很有远见,他们专注于在jQuery库中提供最常用的功能和基础设置,同时包括许多扩展点,以便在以后添加功能。这些增强功能在整合入jQuery后,就会和内置的功能一样。

jQuery有许多扩展点,每一个都允许开发者增强某一方面的功能。从自定义选择器,到集合和工具插件,到jQuery UI小部件和特效,再到自定义Ajax处理和事件,开发者可以让jQuery按照自己的想法来工作。每一个扩展点都将会在本书以后章节中详细展开。

本章用一个简单的集合插件说明了如何用几行代码创建出一个有用的简单插件。把代码打包在单独的文件中,这样开发者就可以在其他页面中进行重用。

在下一章中,读者将会看到如何通过在内置选择器的基础上添加一个自定义选择器来扩展jQuery——这是开发者能做的最简单的扩展。


本章涵盖以下内容:

前一章中介绍的集合插件用来操作在页面上通过选择或遍历得到的一组元素。但是开发者也可以创建一些不操作集合元素,而是在jQuery框架上提供一些工具函数的插件。这就是函数插件

这种类型插件的例子包括Debug插件http://jquery.glyphix.com/,用来记录一些调试信息;还包括Cookie插件,用来操作网站的cookie(将在6.2节中详述)。与前面的插件一样,只有想不到,没有做不到。

因为函数插件不操作元素集合,也通常不与UI组件打交道,所以它们非常容易实现。尽管开发者可以把这些函数定义为独立的JavaScript函数,但是把它们创建在jQuery的命名空间中可以得到很多好处。这样做可以降低全局命名空间的混乱,同时也降低了命名冲突的风险。它们通常也会使用jQuery本身,把它们包含在jQuery中能提供一致的使用方式。它们还旨在提供更易用的功能以及隐藏跨浏览器的差异(jQuery背后的核心原则)。

在第5章中,通过扩展$.fn来定义开发者的集合插件,把它集成到jQuery内置的集合处理中。对于函数插件,开发者直接扩展jQuery($),并且直接通过它来调用。

作为函数插件的一个具体例子,开发者可以开发一个工具来协助自己网页的本地化。它根据特定的语言和地区,只加载必需的JavaScript文件来定制开发者的站点。

基于5.5.2节中描述的本地化方案,这个工具假定相关的JavaScript文件只由它们的语言或地区码来区别。当发生请求时,这个插件以语言和地区码的升序来加载这些文件,每个都覆盖前一个,这样能得到给定的语言和地区的最佳匹配结果。

例如,假定开发者有表6.1中的这些文件。每一个都代表不同的语言和地区组合,并设置一个公共变量(greeting)来显示消息。

表6.1 本地化设置

文 件

语言/地区

消 息

greeting.js

Default

Hello

greeting-en.js

English

Good day

greeting-en-US.js

English (US)

Hi

greeting-en-AU.js

English (Australia)

G’day

greeting-fr.js

French

Bonjour

为了把自己的页面欢迎词本地化为一种特定语言,开发者可以使用这段代码:

这个插件将顺序加载下列文件,从最少匹配到最佳匹配——greeting.js,greeting- en.js,greeting-en-AU.js——得到最匹配的澳大利亚英语:“G’day”。如果请求的语言是加拿大英语(en-CA),因为没有greeting-en-CA.js文件,链条将在第二个文件时停止(标准英语),它将产生欢迎语“Good day”。如果请求了科萨语(xh),会得到默认欢迎词:“Hello”。

当这个文件被加载和执行之后,就可以以通常的方式访问它们设置的那个变量。

如果调用localise()时没有指定任何语言,它就使用浏览器的默认语言。可以通过$.localise.default
Language容易地得到这个默认语言。

本地化不仅限于显示给最终用户的文本,还可以影响显示和外观的其他方面。图6.1展示了Datepicker的一些本地化。

除了文本的变化,这些版本之间还有一些不同:

图6.1 Datepicker本地化:法语、日语和阿拉伯语

现在读者应该知道这个插件的设计目的了,可以使用前一章中介绍的原则和框架来实现它。

尽管上一章中介绍的插件框架大部分都不适用于函数插件,但是还是有几个应该保留的特性。开发者应该继续坚持“利用作用域隐藏实现细节”和“不要依赖$与jQuery的等同性”。解决方案与前面介绍的相同。

程序清单6.1 封装插件代码

通过定义一个匿名函数来创建一个作用域1,立即调用它来创建它的作用域并执行它内部的代码2。通过定义一个参数$并且在调用时为其提供jQuery的引用,保证了它们在函数体内指向同一个对象。

这个插件同时也遵守了“在所有地方使用唯一的名字”和“把一切都放在jQuery对象中”原则。这里不必支持链式调用,因为不牵扯jQuery集合。当没有指定语言时使用浏览器的默认语言,这遵守了”使用合理的默认值”原则。

程序清单6.2展示的localise函数实现了插件的主要功能:根据请求的语言和地区,加载一个或多个本地化文件。

程序清单6.2 声明插件函数

通过把这个函数声明为一个属性,把它直接附加到jQuery中1。然后就可以在开发者的页面上通过 jQuery 对象来访问这个函数。不需要为它选择任何操作元素,因为它应用于整个页面。

这个函数通过多个参数来改变它的行为。除了第一个参数,其余都是可选的。如果没有设置,则使用一个合适的默认值。使用它们的类型来确定它们所代表的含义。程序清单6.3展示了如何处理这些参数。

开发者必须指定一个(string)或一组(string)包名,以供这个函数使用。因为其余的参数都是可选的,代码就必须能区分它们。第二个参数是一个可选的语言代码(string)或者一组设置(object),它的每个属性都是一个独立的参数。为了使后续的处理更容易,所有单独的参数值都被收集到一个设置对象中,就像最初就提供了这个对象一样。如果第二个参数不是这些类型,这些参数被顺序移动1并继续处理下一个。

其余的参数包括一个用来指定是否需要重新加载基础本地化文件的可选标志(boolean)2,一个(string)或一组(string)可选的路径用来指定从哪里找到本地化文件3,一个可选的超时时间(number)4,一个可选的异步标志(boolean)5,以及一个可选的加载完成时的回调函数。缺失的参数被设置为默认值。

程序清单6.3 参数的默认值和标准化

CX6D3.jpg
CX6D3B.jpg

根据参数中提供的设置对象(覆盖所有默认值)或者单个参数值来创建一个累积设置对象6。检查path是一个还是多个路径,然后把它转换为后面需要的格式7。把后面Ajax需要用到的一些选项收集起来以便于后续使用8

当参数处理完成之后,这个插件接下来依次处理所有指定的包。

程序清单6.4 加载本地化文件

CX6D4.jpg
CX6D4B.jpg

开发者定义了一个内部函数1来处理单个包。每个都加载为基础文件(如果设置了加载基础)2,然后加上2字符的语言代码3,最后再加上一个5字符的语言和地区代码(如果有)4。这些文件被放在一个队列中以便顺序读取。

使用jQuery内置的ajax函数来加载单个文件5,从队列中的第一个文件开始,指定返回内容是“script”并以这个类型执行。因为默认使用同步加载(为了保证后续的代码可以依赖返回的内容),所以有一个超时时间。或者可以在调用localise时指定一个额外的参数来使用异步加载,同时指定一个在加载完成时调用的回调函数6。如果队列中还有其他文件,则递归调用处理下一个7

当单个包和其中文件的处理流程定义好之后,找到需要的语言和地区8,然后依次加载每个包9

为了实现这个插件所宣扬的功能,这里定义了另一个函数来提供地方化的版本:

本书的网站上可以下载到这个插件的完整代码。

函数插件的另一个很好的例子是Klaus Hartl写的Cookie插件https://github.com/carhartl/ jquery-cookie。它允许开发者以一种很简单的方式来读写页面上的 cookie,而不需要知道这些cookie使用的格式和编码。开发者可以在每个用户的电脑上保存一些网站的状态信息来增强用户体验。因此,它不操作页面上的元素集合。

Cookies是存储在用户机器上并与一个或几个页面相关联的少量数据。一个网页的cookie在它的页面上是可访问的,并在每次请求时都会被回传到服务器上,这样就可以把一些状态维护在客户端机器上。Cookie在一定时间后会过期,并从用户机器上被删除。

要使用Cookie插件为当前页面设置一个cookie,开发者需要指定它的名字和值。例如,为了标识是否已经在每个用户第一次访问网站时显示了介绍信息,开发者可以在 cookie 中保存这个信息:

开发者也可以提供额外的参数来定制 cookie,设置它的过期时间(默认情况下,cookie随着当前会话的结束而过期)、它要应用的域和路径、是否需要安全传输、是否需要加密cookie值:

获取cookie值时只需要提供它的名字。如果给定的名字没有cookie,则返回null。在网站介绍信息的例子中,开发者应该检查这个值,仅在它为null的情况下显示介绍信息:

通过把cookie的值设置为null来删除它:

正如读者看到的,这个插件遵守了“在所有地方使用唯一的名字”原则。根据每次调用所提供的参数个数和类型,它提供了不同的功能。

现在读者已经知道 Cookie 插件能做什么了,接下来将会看到如何实现它的功能。尽管Cookie插件没有使用笔者的框架,但基本结构和原则仍然适用。

与之前的控件一样,它的代码对于其余的JavaScript世界来说都是受保护的,唯一访问点就是jQuery对象自己。

程序清单6.5 封装插件代码

通过一个匿名函数1把这个插件与外部 JavaScript 隔离,并遵守了“利用作用域隐藏实现细节”和“不要依赖$与jQuery的等同性”原则2。这个插件极少使用jQuery自己,它只定义了一个函数——Cookie,并把它添加到jQuery对象中3,这使用了另外两个原则:“在所有地方使用唯一的名字”和“把一切都放在jQuery对象中”。

这个插件有两个操作模式——读和写cookie,使用哪个模式则由调用时传入的参数个数和类型来决定。首先来处理写cookie的情况。

程序清单6.6 写一个cookie值

如果提供了不止一个参数,并且第二个不是一个object,则为写cookie模式1。如果值为null,则删除cookie2,把超时时间设置为-1,代表这个 cookie已经过期并作废。如果expires选项是一个数字,则被认为是从今天开始的天数3。最终,cookie值被转换为字符串,这个 cookie 和它的设置一起被写入浏览器4。正如预期的那样使用了“使用合理的默认值”原则,使得当前域和路径上的 cookie 随着当前会话的结束而过期。编码后的cookie名和值作为函数的调用结果返回,尽管大部分时候开发者不需要知道或使用这个值。

如果是取值模式,插件将继续处理,代码如程序清单6.7所示。

程序清单6.7 读取一个cookie值

首先,读取作为第二个参数传入的所有选项1。如果没有提供,则使用默认值。获取当前cookie值(当前页面上的所有cookie),并分离为独立的键值对2。根据传入的名字检查每一对3,并返回相应的值。如果没有匹配到,则返回nul4

开发者可以通过更新$.cookie.defaults来设置所有cookies的默认选项:

Cookie插件的完整代码可以从本书的网站上下载。

需要知道


开发函数插件来添加不直接操作选定元素的功能。

直接扩展$来添加额外的功能。

通过使用作用域来保护自己的代码以及防止名字冲突。

通过参数控制插件的行为,但是没有设置参数时要提供合适的默认值。

自己试试看


写一个函数插件来格式化时间,调用方式如下:

var time = $.formatTime(new Date(0, 0, 0, 12, 34, 0));

接收一个Date参数对象,从中提取时间。如果没有设置,则使用当前时间。把时间格式化为hh:mmAP。想进一步挑战的话,添加可选的第一个参数(Boolean)用来指定是否格式化为12时制,或者24时制。

提示: Date对象有getHours和getMinutes函数。使用new Date()获取当前日期/时间。

集合插件操作通过选择或遍历得到的元素集合,而函数插件并不应用于这种集合。它们在页面上提供一些工具函数使得一系列交互变得简单。它们隐藏了页面上的一些繁琐的内部工作,并且消除了跨浏览器差异所带来的一些问题。

Localization插件和Cookie插件这两个例子在实践中展示了如何创建函数插件。它们示范了如何把插件框架应用于这种新的插件类型,以及为什么仍然需要遵守这些最佳实践原则。

当开发者已经创建了自己的插件时,需要确保它能正常工作,并让其他人能轻易地获取和理解如何使用它。下一章将介绍如何为开发者的插件进行测试、打包、部署和文档书写,使它可以被推向更广阔的jQuery社区。


相关图书

深入浅出Spring Boot 3.x
深入浅出Spring Boot 3.x
JavaScript核心原理:规范、逻辑与设计
JavaScript核心原理:规范、逻辑与设计
JavaScript入门经典(第7版)
JavaScript入门经典(第7版)
JavaScript函数式编程指南
JavaScript函数式编程指南
PHP、MySQL和JavaScript入门经典(第6版)
PHP、MySQL和JavaScript入门经典(第6版)
JavaScript学习指南(第3版)
JavaScript学习指南(第3版)

相关文章

相关课程