关键字:   jQuery    

这份指南是对jQeury库的介绍,它需要对JavaScript和文档对象模型(DOM)有基本的了解。它从零开始讲解并解释必要的细节。
该指南讲到了一个简单的hello world例子,selector和event基础,AJAX,FX以及使用和创作plugins。
这份指南不包含"click me"例子,只提供"copy me"代码的意图是激发你来自己尝试例子。Copy一个例子,看看它做什么,并修改它。

目录
1 Setup
2 Hello jQuery
3 Find me: 使用selectors和events
4 Rate me: 使用Ajax
5 Animate me: 使用Effects
6 Sort me: 使用tablesorter plugin
7 Plug me: 写你自己的plugins
8 Next steps

Setup
我们首先需要jQuery库的copy来开始。最新的版本可以在http://docs.jquery.com/Downloading_jQuery找到,这份指南也提供一个基本包来下载。
jQuery Starterkit
下载该文件并解压,用你最喜欢的编辑器打开starterkit.html和custom.js并用浏览器打开starterkit.html。
现在我们准备好了开始著名的"Hello world"例子的任何事情。
本节里有意思的链接:
jQuery Starterkit
Downloading jQuery

Hello jQuery
当我们使用jQuery时所做的几乎任何事情都会读取或操作文档对象模型(DOM),我们需要确认一旦DOM准备好了则我们开始添加events等东西。
为了做这件事,我们为document注册一个ready事件。

代码
  1. $(document).ready(function() {  
  2.     // do stuff when DOM is ready  
  3. });  

在该方法里放入一个alert不会有多大意义,因为alert不需要DOM成功loaded。所以让我们尝试一些更复杂的东西:当点击该链接时显示一个alert。
代码
  1. $(document).ready(function() {  
  2.     $("a").click(function() {  
  3.         alert("Hello world!");  
  4.     });  
  5. });  

这将在你点击该链接时显示alert。
让我们看看我们做了什么:$("a")是一个jQuery selector,在这里,它选择所有的a元素。$本身为jQuery"类"的别名,因此$()构建了一个jQuery对象。
我们下一步调用的click()方法为该jQuery对象的一个方法。它绑定了一个click事件到所有被选择的元素(在这里为一个单独的anchor元素)并当事件发生时执行
提供的方法。
这与下面的代码类似:
代码
  1. <a href="" onclick="alert('Hello world')">Link</a>  

区别非常明显:我们不需要为每个单独的元素写一个onclick。对结构(HTML)和行为(JS)我们有一个清晰的分离,就像我们使用CSS来分离结构和呈现。
了解了这些,我们来对selectors和events做一些更多的东西。
本节里有意思的链接:
jQuery Base
jQuery Expressions
jQuery Basic Events

Find me: 使用selectors和events
jQuery提供了两种方式来选择元素。第一种使用作为字符串传递给jQuery构造器的CSS和XPath选择器的联合(例如$("div > ul a"))。第二种使用jQuery对象的
一些方法。两种方式可以联合。
我们选择并修改我们的starterkit里的第一个排序列表来尝试一些选择器。
我们以选择列表本身开始。列表有一个ID "orderedlist"。在传统的JavaScript里,你可以通过使用document.getElementById("orderedlist")来使用它。使用
jQuery的话,我们像这样做:

代码
  1. $(document).ready(function() {  
  2.     $("#orderedlist").addClass("red");  
  3. });  

starterkit提供了一个带有一个class为"red"的简单的添加一个红色背景的stylesheet。因此,当你在浏览器里reload页面时,你应该看到第一个ordered list
将拥有一个红色背景。第二个list则没变。
现在让我们添加一些classes到该list的子元素中。
代码
  1. $(document).ready(function() {  
  2.     $("#orderedlist > li").addClass("blue");  
  3. });  

这将选择id为orderedlist的元素的所有子li元素并为其添加class "blue"。
现在看看一个更复杂的:我们希望当用户hover到该list的最后一个li元素时添加和删除class。
代码
  1. $(document).ready(function() {  
  2.     $("#orderedlist li:last").hover(function() {  
  3.         $(this).addClass("green");  
  4.     },function() {  
  5.         $(this).removeClass("green");  
  6.     });  
  7. });  

有许多其他类似于CSSXPath语法的选择器。更多的例子以及一个所有可得到的表达式的列表可以在这里找到。
对每个可得到的onxxx事件,像onclick,conchange,onsubmit,都有一个jQuery等价物。一些其他的事件,像ready和hover,被提供来作为方法方便某些任务。
你可以在jQuery Events Documentation里找到完整的事件列表。
使用这些selectors和events你已经可以做许多事情,但是这里还有一个。
代码
  1. $(document).ready(function() {  
  2.     $("#orderedlist").find("li").each(function(i) {  
  3.         $(this).append(" BAM! " + i);  
  4.     });  
  5. });  

find()允许你对已经选择的元素做更深的子搜索,因此$("#orderedlist").find("li")几乎和$("#orderedlist li")一样。
each()对每个元素迭代并允许更多的处理。大多数方法,像addClass(),自己使用each()。
在这个例子中,append()用来在每个元素的末尾添加一些文本。
另外一个你经常面对的任务是在jQuery没有cover的DOM元素上调用方法。考虑一个你想在通过AJAX成功提交后reset它的form。
代码
  1. $(document).ready(function() {  
  2.     // use this to reset a single form  
  3.     $("#reset").click(function() {  
  4.         $("#form").reset();  
  5.     });  
  6. });  

这些代码选择ID为"form"的元素并对每个选择的元素调用reset()。当你有多于一个form时,你也可以这样做:
代码
  1. $(document).ready(function() {  
  2.     // use this to reset several forms at once  
  3.     $("#reset").click(function() {  
  4.         $("form").reset();  
  5.     });  
  6. });  

这将在你的document里选择所有的forms,迭代它们并对每个调用reset()。
另一个你可能面临的问题是不选择某一个元素。jQuery为它提供filter()和not()。filter()通过满足该filter表达式来减少选择的元素,not()则相反删除掉
所有满足该表达式的元素。考虑一个unordered的list,你想选择所有没有ul子元素的li元素。
代码
  1. $(document).ready(function() {  
  2.     $("li").not("[ul]").css("border", "1px solid black");  
  3. });  

这将选择所有的li元素并删除有ul子元素的元素。因此所有的li元素将有一个border,除了有ul子元素的。[expression]语法来自XPath并且可以用来被子元素
和属性filter。可能你想选择所有的有一个name属性的anchors:
代码
  1. $(document).ready(function() {  
  2.     $("a[@name]").background("#eee");  
  3. });  

这将对所有的有一个name属性的anchor元素添加一个background颜色。
比通过name选择anchors更常用的是,你可能需要通过它们的"href"属性选择anchors。由于浏览器的行为不一致这可能返回不同的"href"值(注意:这个问题最近
在jQuery中解决了,只要在1.1.1版本后都可以)。为了只匹配一部分值,我们可以使用包含选择"*="来代替等于"=":
代码
  1. $(document).ready(function() {  
  2.     $("a[@href*=/content/gallery]").click(function() {  
  3.         // do something with all links that point somewhere to /content/gallery  
  4.     });  
  5. });  

到目前为止,所有的selectors用来选择子或filter当前选择。还有你需要选择前一个或下一个元素的情况,即所谓的siblings。考虑FAQ页面,所有的答案首先
隐藏,而当问题点击时显示。该jQuery代码为:
代码
  1. $(document).ready(function() {  
  2.     $('#faq').find('dd').hide().end().find('dt').click(function() {  
  3.         $(this).next().slideToggle();  
  4.     });  
  5. });  

这里我们使用链来减少代码量并得到更好的性能,因为'#faq'只选择了一次。
通过使用end(),第一个find()不会结束,则我们可以对#faq元素继续搜索下一个find(),而不是对dd子元素操作。
在click处理器即传递给click()方法的function里,我们使用$(this).next()来从当前dt查找下一个sibling。这允许我们快速选择紧跟在点击的问题后的答案。
除了sibling,你也可以选择父元素(对属性XPath的人而言为所谓的ancestors)。你可能想对用户hover的链接的父paragraph高亮,试试这个:
代码
  1. $(document).ready(function() {  
  2.     $("a").hover(function() {  
  3.         $(this).parents("p").addClass("highlight");  
  4.     },function() {  
  5.         $(this).parents("p").removeClass("highlight");  
  6.     });  
  7. });  

对于所有hover的anchor元素,搜索它的父paragraph并添加和删除一个"highlight" class。
让我们继续之前了解一下:jQuery很多时候是让代码变得更短而更容易阅读和维护。以下是一个$(document).ready(callback)记号的捷径:
代码
  1. $(function() {  
  2.     // code to execute when the DOM is ready  
  3. });  

对于Hello world!例子,我们可以这样写:
代码
  1. $(function() {  
  2.     $("a").click(function() {  
  3.         alert("Hello world!");  
  4.     });  
  5. });  

现在有了基本知识后,我们想explore一些其它方面,开始使用AJAX。
本节里有意思的链接:
jQuery API documentation
Visual jQuery - A catgorized browsable API documentation.
jQuery Selectors
jQuery Events
jQuery DOM Traversing

Rate me: 使用Ajax
在这个部分我们写一个小Ajax程序,它允许用户rate something,就像在youtube.com上做的一样。
我们需要一些服务器端代码来完成这个。我的例子使用php文件来读"rating"参数并返回ratings的数量和平均的rating。看看rate.php的服务器端代码。
我们想让这个例子用Ajax来工作,因此我们用jQuery生成一些必要的东西并加到一个ID为"rating"的容器里

代码
  1. $(document).ready(function() {  
  2.     // generate markup  
  3.     $("#rating").append("Please rate: ");  
  4.   
  5.     for ( var i = 1; i <=5; i++ )  
  6.         $("#rating").append("<a href='#'>" + i + "</a>");  
  7.   
  8.     // add markup to container and applier click handlers to anchors  
  9.     $("$raing a ").click(function(e)   
  10.         // send request  
  11.         $.post("rate.php", {rating: $(this).html()}, function(xml) {  
  12.             // format and output result  
  13.             $("#rating").html(  
  14.                 "Thanks for rating, current average: " +   
  15.                 $("average", xml).text() +  
  16.                 ", number of votes: " +  
  17.                 $("count", xml).text()  
  18.             );  
  19.         });  
  20.   
  21.         // stop normal link click  
  22.         return false;  
  23.     });  
  24. });  

这个代码片段生成5个anchor元素并把它们添加到id为"rating"的容器元素。最后,对容器里的每个anchor添加一个click处理器。当点击anchor时,一个以anchor
的内容为参数的post请求发送到rate.php。结果作为一个XML返回,并添加到容器代替anchors。
如果你手头上没有一个安装的PHP服务器,你可以看看一个online example。对于一个非常好的甚至不用JavaScript工作的rating系统的例子,访问softonic.de
点击"Kurz bewerten!"
jQuery的Ajax方法的更多的文档可以在Ajax Documentation或者用Ajax开发的Visual jQuery上找到。
当通过Ajax载入内容时遇到的一个非常常见的问题是:当添加事件处理器到你的文档时,如果事件处理器也适合载入的内容,则你必须在内容载入之后也添加这些
处理器。为了防止代码重复,你可以写一个方法代理。例如:
代码
  1. function addClickHandlers() {  
  2.     $("a.remote", this).click(function() {  
  3.         $("#target").load(this.href, addClickHandlers);  
  4.     });  
  5. }  
  6. $(document).ready(addClickHandlers);  

现在一旦当DOM为ready以及每次当一个用户点击class为remote的链接并且内容完成载入后addClickHandlers都会被调用。
注意$("a.remote", this)查询,this传递过来作为一个context:对于document ready事件,this表示document,则它搜索整个document中class为remote的anchors
当addClickHandlers用来作为load()的回调时,this表示另一个不同的元素:在这个例子中,表示id为target的元素。这防止了click事件一次又一次的赋给同一
链接,从而最终导致崩溃。
回调的另一个常见的问题是参数。你已经指定了你的回调但是需要传递一个额外的参数。达到次目标的最简单的方式是在另一个方法里包装回调:
代码
  1. // get some data  
  2. var foobar = ...;  
  3.   
  4. // specify handler, it needs data as a parameter  
  5. function handler(data) {  
  6.     // ...  
  7. }  
  8.   
  9. // add click handler and pass foobar!  
  10. $('a').click(function() {  
  11.     handler(foobar);  
  12. });  
  13.   
  14. // if you need the context of the original handler, use apply:  
  15. $('a').click(function() {  
  16.     handler.apply(this, [foobar]);  
  17. });  

使用Ajax我们可以cover许多"Web 2.0"。既然我们已经看了一些基本的Ajax,让我们添加一些简单的effects和animations到页面中。
本节有意思的链接:
jQuery Ajax Documentation
jQuery API - 包含所有的jQuery方法的描述和例子
Thick Box - 一个使用jQuery来加强著名的lightbox的jQuery插件

Animate me: 使用Effects
可以使用jQuery的show()和hide()构建的简单的animations。

代码
  1. $(document).ready(function() {  
  2.     $("a").toggle(function() {  
  3.         $(".stuff").hide('slow');  
  4.     },function() {  
  5.         $(".stuff").show('fast');  
  6.     });  
  7. });  

你可以使用animate()创建任何animations的联合。例如,一个具有fade的slide:
代码
  1. $(document).ready(function() {  
  2.     $("a").toggle(function() {  
  3.         $(".stuff").animate({ height: 'hide', opacity: 'hide' }, 'slow');  
  4.     },function() {  
  5.         $(".stuff").animate({ height: 'show', opacity: 'show' }, 'slow');  
  6.     });  
  7. });  

更炫的effects可以在interface plugin collection找到。该站点提供demos和文档。虽然Interface在jQuery的插件列表的最前面,还有许多其他的插件。下一
部分显示了怎样使用tablesorter插件。
本节有意思的链接:
jQuery Effects Documentation
Interface plugin

Sort me: 使用tablesorter plugin
tablesorter插件允许在客户端对表格排序。你只需引入jQuery和插件,并告诉插件哪个表格是你想排序的。
添加以下内容到starterkit.html(下jquery引入的下面)来尝试该例子:

代码
  1. <script src="lib/jquery.tablesorterjs"></script>  

引入了该插件后,你可以像这样调用它:
代码
  1. $(document).ready(function() {  
  2.     $("#large").tableSorter();  
  3. });  

试着点击table的头部并看看它怎样在第一次升序排序以及第二次降序排序。该表格可以使用一些行高亮,我们可以通过传递一些选项来添加这个:
代码
  1. $(document).ready(function() {  
  2.     $("#large").tableSorter({  
  3.         // Class names for striping supplied as a array.  
  4.         stripingRowClass: ['odd', 'even'],  
  5.         // Stripe rows on tableSorter init  
  6.         stripeRowsOnStartUp: true  
  7.     });  
  8. });  

tablesorter homepage有更多关于可得到的选项的例子和文档。
大多数插件可以像这样使用:引入插件文件并在某些元素上调用插件方法,传递一些选项设置来定制插件。
一个可得到的up-to-date插件列表可以在jQuery Plugin site找到。
当你使用jQuery的越频繁,你可能发现把你自己的代码打包成一个插件非常有用,可以为你自己或者你的公司重用它,或者与社区分享。下一节讲述了怎样构建
一个插件。
本节有意思的链接:
Plugins for jQuery
Tablesorter Plugin

Plug me: 写你自己的plugins
为jQuery写你自己的插件非常简单。如果你遵循下面的规则,则其他人集成你的插件也非常简单。
插件命名
为你的插件找一个名字,让我们称我们的例子为"foobar"。创建一个名为jquery.[yourpluginname].js文件,例如,jquery.foobar.js。
添加一个自定义方法
通过扩展jQuery对象来创建一个或多个插件方法,例如:

代码
  1. jQuery.fn.foobar = function() {  
  2.     // do something  
  3. };  

则通过执行下面代码就可以得到使用上面的插件:
代码
  1. $(...).foobar();  

默认设置:
创建可以被用户更改的默认设置,例如:
代码
  1. jQuery.fn.foobar = function(options) {  
  2.     var settings = jQuery.extend({  
  3.         value: 5, name: "pete", bar: 655  
  4.     }, options);  
  5. };  

你可以调用该插件而不带选项,即使用默认配置:
代码
  1. $("...").foobar();  

或者带一些选项:
代码
  1. $("...").foobar({ value: 123, bar: 9 });  

文档
如果你发表你的插件,你应该也提供一些例子和文档。有许多插件可以作为很好的参考。
现在你应该具有了写插件的基本知识。让我们来写一个我们自己的插件。
Checkbox插件
很多人使用jQuery来处理表单时会问到radio buttons或checkboxes的checking和unchecking。他们常用这样的代码:
代码
  1. $("input[@type='checkbox']").each(function() {  
  2.     this.checked = true;  
  3.     this.checked = false; // or, to uncheck  
  4.     this.checked = !this.checked; // or, to toggle  
  5. });  

无论何时你的代码里有一个each时,你可能想重写它为一个插件,非常直接:
代码
  1. jQuery.fn.check = function() {  
  2.     return this.each(function() {  
  3.         this.checked = true;  
  4.     });  
  5. };  

现在该插件可以使用了:
代码
  1. $("input[@type='checkbox']").check();  

现在你也可以为uncheck()和toggleCheck()写插件了。但是我们通过扩展我们的插件来接收一些选项来替代。
代码
  1. jQuery.fn.check = function(mode) {  
  2.     // if mode is undefined, use 'on' as default  
  3.     var mode = mode || 'on';  
  4.   
  5.     return this.each(function() {  
  6.         switch(mode) {  
  7.             case 'on':  
  8.                 this.checked = true;  
  9.                 break;  
  10.             case 'off':  
  11.                 this.checked = false;  
  12.                 break;  
  13.             case 'toggle':  
  14.                 this.checked = !this.checked;  
  15.                 break;  
  16.         }  
  17.     });  
  18. };  

我们可以提供选项"on","off"和"toggle"或者默认无选项,例如:
代码
  1. $("input[@type='checkbox']").check();  
  2. $("input[@type='checkbox']").check('on');  
  3. $("input[@type='checkbox']").check('off');  
  4. $("input[@type='checkbox']").check('toggle');  

可选设置
写多于一个设置选项会变得复杂,因为如果用户想省略第一个参数而只使用第二个参数时他必须传递一个null值。
上一节中对tablesorter的使用证明了使用一个对象来解决这个问题。用户可以省略所有的参数或者为每个他想override的设置传递一个具有键/值对的对象。
出于练习,你可以尝试重写第4节的Voting代码为一个插件。插件骨架可能看起来像这样:
代码
  1. jQuery.fn.rateMe = function(options) {  
  2.     // instead of slecting a static container with  
  3.     // $("#rating"), we now use the jQuery context  
  4.     var container = this;  
  5.   
  6.     var settings = jQuery.extend({  
  7.         url: "rate.php"  
  8.         // put more defaults here  
  9.     }, options);  
  10.   
  11.     // ... rest of the code ...  
  12.   
  13.     // if possible, return "this" to not break the chain  
  14.     return this;  
  15. });  

则可以允许你像这样允许该插件:
代码
  1. $(...).rateMe({ url: "test.php" });  

Next steps
如果你计划开发更多的JavaScript,你应该考虑称为FireBug的Firefox插件。它提供一个console(很好的替代alerts),一个debugger和其他有用的stuff来为
JavaScript开发。
如果你有不能解决的问题、想分享的主意或者只是需要用jQuery表达你的看法,请自由舒畅的post给jQuery mailing list
对于与本指南相关的任何东西请在我的blog上post一个comment或者直接联系我。
Whats left...Thanks a lot to John Resig for this greate library! Thanks to the jQuery community for providing John with enough coffee
and everything else!