這份指南是對jQeury庫的介紹,它需要對JavaScript和文檔對象模型(DOM)有基本的了解。它從零開始講解并解釋必要的細節(jié)。
該指南講到了一個簡單的hello world例子,selector和event基礎(chǔ),AJAX,F(xiàn)X以及使用和創(chuàng)作plugins。
這份指南不包含"click me"例子,只提供"copy me"代碼的意圖是激發(fā)你來自己嘗試例子。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。
現(xiàn)在我們準備好了開始著名的"Hello world"例子的任何事情。
本節(jié)里有意思的鏈接:
jQuery Starterkit
Downloading jQuery
Hello jQuery
當(dāng)我們使用jQuery時所做的幾乎任何事情都會讀取或操作文檔對象模型(DOM),我們需要確認一旦DOM準備好了則我們開始添加events等東西。
為了做這件事,我們?yōu)閐ocument注冊一個ready事件。
- $(document).ready(function() {
- // do stuff when DOM is ready
- });
在該方法里放入一個alert不會有多大意義,因為alert不需要DOM成功loaded。所以讓我們嘗試一些更復(fù)雜的東西:當(dāng)點擊該鏈接時顯示一個alert。
- $(document).ready(function() {
- $("a").click(function() {
- alert("Hello world!");
- });
- });
這將在你點擊該鏈接時顯示alert。
讓我們看看我們做了什么:$("a")是一個jQuery selector,在這里,它選擇所有的a元素。$本身為jQuery"類"的別名,因此$()構(gòu)建了一個jQuery對象。
我們下一步調(diào)用的click()方法為該jQuery對象的一個方法。它綁定了一個click事件到所有被選擇的元素(在這里為一個單獨的anchor元素)并當(dāng)事件發(fā)生時執(zhí)行
提供的方法。
這與下面的代碼類似:
- <a href="" onclick="alert('Hello world')">Link</a>
區(qū)別非常明顯:我們不需要為每個單獨的元素寫一個onclick。對結(jié)構(gòu)(HTML)和行為(JS)我們有一個清晰的分離,就像我們使用CSS來分離結(jié)構(gòu)和呈現(xiàn)。
了解了這些,我們來對selectors和events做一些更多的東西。
本節(jié)里有意思的鏈接:
jQuery Base
jQuery Expressions
jQuery Basic Events
Find me: 使用selectors和events
jQuery提供了兩種方式來選擇元素。第一種使用作為字符串傳遞給jQuery構(gòu)造器的CSS和XPath選擇器的聯(lián)合(例如$("div > ul a"))。第二種使用jQuery對象的
一些方法。兩種方式可以聯(lián)合。
我們選擇并修改我們的starterkit里的第一個排序列表來嘗試一些選擇器。
我們以選擇列表本身開始。列表有一個ID "orderedlist"。在傳統(tǒng)的JavaScript里,你可以通過使用document.getElementById("orderedlist")來使用它。使用
jQuery的話,我們像這樣做:
- $(document).ready(function() {
- $("#orderedlist").addClass("red");
- });
starterkit提供了一個帶有一個class為"red"的簡單的添加一個紅色背景的stylesheet。因此,當(dāng)你在瀏覽器里reload頁面時,你應(yīng)該看到第一個ordered list
將擁有一個紅色背景。第二個list則沒變。
現(xiàn)在讓我們添加一些classes到該list的子元素中。
- $(document).ready(function() {
- $("#orderedlist > li").addClass("blue");
- });
這將選擇id為orderedlist的元素的所有子li元素并為其添加class "blue"。
現(xiàn)在看看一個更復(fù)雜的:我們希望當(dāng)用戶hover到該list的最后一個li元素時添加和刪除class。
- $(document).ready(function() {
- $("#orderedlist li:last").hover(function() {
- $(this).addClass("green");
- },function() {
- $(this).removeClass("green");
- });
- });
有許多其他類似于CSS和XPath語法的選擇器。更多的例子以及一個所有可得到的表達式的列表可以在這里找到。
對每個可得到的onxxx事件,像onclick,conchange,onsubmit,都有一個jQuery等價物。一些其他的事件,像ready和hover,被提供來作為方法方便某些任務(wù)。
你可以在jQuery Events Documentation里找到完整的事件列表。
使用這些selectors和events你已經(jīng)可以做許多事情,但是這里還有一個。
- $(document).ready(function() {
- $("#orderedlist").find("li").each(function(i) {
- $(this).append(" BAM! " + i);
- });
- });
find()允許你對已經(jīng)選擇的元素做更深的子搜索,因此$("#orderedlist").find("li")幾乎和$("#orderedlist li")一樣。
each()對每個元素迭代并允許更多的處理。大多數(shù)方法,像addClass(),自己使用each()。
在這個例子中,append()用來在每個元素的末尾添加一些文本。
另外一個你經(jīng)常面對的任務(wù)是在jQuery沒有cover的DOM元素上調(diào)用方法。考慮一個你想在通過AJAX成功提交后reset它的form。
- $(document).ready(function() {
- // use this to reset a single form
- $("#reset").click(function() {
- $("#form").reset();
- });
- });
這些代碼選擇ID為"form"的元素并對每個選擇的元素調(diào)用reset()。當(dāng)你有多于一個form時,你也可以這樣做:
- $(document).ready(function() {
- // use this to reset several forms at once
- $("#reset").click(function() {
- $("form").reset();
- });
- });
這將在你的document里選擇所有的forms,迭代它們并對每個調(diào)用reset()。
另一個你可能面臨的問題是不選擇某一個元素。jQuery為它提供filter()和not()。filter()通過滿足該filter表達式來減少選擇的元素,not()則相反刪除掉
所有滿足該表達式的元素。考慮一個unordered的list,你想選擇所有沒有ul子元素的li元素。
- $(document).ready(function() {
- $("li").not("[ul]").css("border", "1px solid black");
- });
這將選擇所有的li元素并刪除有ul子元素的元素。因此所有的li元素將有一個border,除了有ul子元素的。[expression]語法來自XPath并且可以用來被子元素
和屬性filter。可能你想選擇所有的有一個name屬性的anchors:
- $(document).ready(function() {
- $("a[@name]").background("#eee");
- });
這將對所有的有一個name屬性的anchor元素添加一個background顏色。
比通過name選擇anchors更常用的是,你可能需要通過它們的"href"屬性選擇anchors。由于瀏覽器的行為不一致這可能返回不同的"href"值(注意:這個問題最近
在jQuery中解決了,只要在1.1.1版本后都可以)。為了只匹配一部分值,我們可以使用包含選擇"*="來代替等于"=":
- $(document).ready(function() {
- $("a[@href*=/content/gallery]").click(function() {
- // do something with all links that point somewhere to /content/gallery
- });
- });
到目前為止,所有的selectors用來選擇子或filter當(dāng)前選擇。還有你需要選擇前一個或下一個元素的情況,即所謂的siblings。考慮FAQ頁面,所有的答案首先
隱藏,而當(dāng)問題點擊時顯示。該jQuery代碼為:
- $(document).ready(function() {
- $('#faq').find('dd').hide().end().find('dt').click(function() {
- $(this).next().slideToggle();
- });
- });
這里我們使用鏈來減少代碼量并得到更好的性能,因為'#faq'只選擇了一次。
通過使用end(),第一個find()不會結(jié)束,則我們可以對#faq元素繼續(xù)搜索下一個find(),而不是對dd子元素操作。
在click處理器即傳遞給click()方法的function里,我們使用$(this).next()來從當(dāng)前dt查找下一個sibling。這允許我們快速選擇緊跟在點擊的問題后的答案。
除了sibling,你也可以選擇父元素(對屬性XPath的人而言為所謂的ancestors)。你可能想對用戶hover的鏈接的父paragraph高亮,試試這個:
- $(document).ready(function() {
- $("a").hover(function() {
- $(this).parents("p").addClass("highlight");
- },function() {
- $(this).parents("p").removeClass("highlight");
- });
- });
對于所有hover的anchor元素,搜索它的父paragraph并添加和刪除一個"highlight" class。
讓我們繼續(xù)之前了解一下:jQuery很多時候是讓代碼變得更短而更容易閱讀和維護。以下是一個$(document).ready(callback)記號的捷徑:
- $(function() {
- // code to execute when the DOM is ready
- });
對于Hello world!例子,我們可以這樣寫:
- $(function() {
- $("a").click(function() {
- alert("Hello world!");
- });
- });
現(xiàn)在有了基本知識后,我們想explore一些其它方面,開始使用AJAX。
本節(jié)里有意思的鏈接:
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上做的一樣。
我們需要一些服務(wù)器端代碼來完成這個。我的例子使用php文件來讀"rating"參數(shù)并返回ratings的數(shù)量和平均的rating。看看rate.php的服務(wù)器端代碼。
我們想讓這個例子用Ajax來工作,因此我們用jQuery生成一些必要的東西并加到一個ID為"rating"的容器里
- $(document).ready(function() {
- // generate markup
- $("#rating").append("Please rate: ");
- for ( var i = 1; i <=5; i++ )
- $("#rating").append("<a href='#'>" + i + "</a>");
- // add markup to container and applier click handlers to anchors
- $("$raing a ").click(function(e)
- // send request
- $.post("rate.php", {rating: $(this).html()}, function(xml) {
- // format and output result
- $("#rating").html(
- "Thanks for rating, current average: " +
- $("average", xml).text() +
- ", number of votes: " +
- $("count", xml).text()
- );
- });
- // stop normal link click
- return false;
- });
- });
這個代碼片段生成5個anchor元素并把它們添加到id為"rating"的容器元素。最后,對容器里的每個anchor添加一個click處理器。當(dāng)點擊anchor時,一個以anchor
的內(nèi)容為參數(shù)的post請求發(fā)送到rate.php。結(jié)果作為一個XML返回,并添加到容器代替anchors。
如果你手頭上沒有一個安裝的PHP服務(wù)器,你可以看看一個online example。對于一個非常好的甚至不用JavaScript工作的rating系統(tǒng)的例子,訪問softonic.de并
點擊"Kurz bewerten!"
jQuery的Ajax方法的更多的文檔可以在Ajax Documentation或者用Ajax開發(fā)的Visual jQuery上找到。
當(dāng)通過Ajax載入內(nèi)容時遇到的一個非常常見的問題是:當(dāng)添加事件處理器到你的文檔時,如果事件處理器也適合載入的內(nèi)容,則你必須在內(nèi)容載入之后也添加這些
處理器。為了防止代碼重復(fù),你可以寫一個方法代理。例如:
- function addClickHandlers() {
- $("a.remote", this).click(function() {
- $("#target").load(this.href, addClickHandlers);
- });
- }
- $(document).ready(addClickHandlers);
現(xiàn)在一旦當(dāng)DOM為ready以及每次當(dāng)一個用戶點擊class為remote的鏈接并且內(nèi)容完成載入后addClickHandlers都會被調(diào)用。
注意$("a.remote", this)查詢,this傳遞過來作為一個context:對于document ready事件,this表示document,則它搜索整個document中class為remote的anchors
當(dāng)addClickHandlers用來作為load()的回調(diào)時,this表示另一個不同的元素:在這個例子中,表示id為target的元素。這防止了click事件一次又一次的賦給同一
鏈接,從而最終導(dǎo)致崩潰。
回調(diào)的另一個常見的問題是參數(shù)。你已經(jīng)指定了你的回調(diào)但是需要傳遞一個額外的參數(shù)。達到次目標的最簡單的方式是在另一個方法里包裝回調(diào):
- // get some data
- var foobar = ...;
- // specify handler, it needs data as a parameter
- function handler(data) {
- // ...
- }
- // add click handler and pass foobar!
- $('a').click(function() {
- handler(foobar);
- });
- // if you need the context of the original handler, use apply:
- $('a').click(function() {
- handler.apply(this, [foobar]);
- });
使用Ajax我們可以cover許多"Web 2.0"。既然我們已經(jīng)看了一些基本的Ajax,讓我們添加一些簡單的effects和animations到頁面中。
本節(jié)有意思的鏈接:
jQuery Ajax Documentation
jQuery API - 包含所有的jQuery方法的描述和例子
Thick Box - 一個使用jQuery來加強著名的lightbox的jQuery插件
Animate me: 使用Effects
可以使用jQuery的show()和hide()構(gòu)建的簡單的animations。
- $(document).ready(function() {
- $("a").toggle(function() {
- $(".stuff").hide('slow');
- },function() {
- $(".stuff").show('fast');
- });
- });
你可以使用animate()創(chuàng)建任何animations的聯(lián)合。例如,一個具有fade的slide:
- $(document).ready(function() {
- $("a").toggle(function() {
- $(".stuff").animate({ height: 'hide', opacity: 'hide' }, 'slow');
- },function() {
- $(".stuff").animate({ height: 'show', opacity: 'show' }, 'slow');
- });
- });
更炫的effects可以在interface plugin collection找到。該站點提供demos和文檔。雖然Interface在jQuery的插件列表的最前面,還有許多其他的插件。下一
部分顯示了怎樣使用tablesorter插件。
本節(jié)有意思的鏈接:
jQuery Effects Documentation
Interface plugin
Sort me: 使用tablesorter plugin
tablesorter插件允許在客戶端對表格排序。你只需引入jQuery和插件,并告訴插件哪個表格是你想排序的。
添加以下內(nèi)容到starterkit.html(下jquery引入的下面)來嘗試該例子:
- <script src="lib/jquery.tablesorterjs"></script>
引入了該插件后,你可以像這樣調(diào)用它:
- $(document).ready(function() {
- $("#large").tableSorter();
- });
試著點擊table的頭部并看看它怎樣在第一次升序排序以及第二次降序排序。該表格可以使用一些行高亮,我們可以通過傳遞一些選項來添加這個:
- $(document).ready(function() {
- $("#large").tableSorter({
- // Class names for striping supplied as a array.
- stripingRowClass: ['odd', 'even'],
- // Stripe rows on tableSorter init
- stripeRowsOnStartUp: true
- });
- });
在tablesorter homepage有更多關(guān)于可得到的選項的例子和文檔。
大多數(shù)插件可以像這樣使用:引入插件文件并在某些元素上調(diào)用插件方法,傳遞一些選項設(shè)置來定制插件。
一個可得到的up-to-date插件列表可以在jQuery Plugin site找到。
當(dāng)你使用jQuery的越頻繁,你可能發(fā)現(xiàn)把你自己的代碼打包成一個插件非常有用,可以為你自己或者你的公司重用它,或者與社區(qū)分享。下一節(jié)講述了怎樣構(gòu)建
一個插件。
本節(jié)有意思的鏈接:
Plugins for jQuery
Tablesorter Plugin
Plug me: 寫你自己的plugins
為jQuery寫你自己的插件非常簡單。如果你遵循下面的規(guī)則,則其他人集成你的插件也非常簡單。
插件命名
為你的插件找一個名字,讓我們稱我們的例子為"foobar"。創(chuàng)建一個名為jquery.[yourpluginname].js文件,例如,jquery.foobar.js。
添加一個自定義方法
通過擴展jQuery對象來創(chuàng)建一個或多個插件方法,例如:
- jQuery.fn.foobar = function() {
- // do something
- };
則通過執(zhí)行下面代碼就可以得到使用上面的插件:
- $(...).foobar();
默認設(shè)置:
創(chuàng)建可以被用戶更改的默認設(shè)置,例如:
- jQuery.fn.foobar = function(options) {
- var settings = jQuery.extend({
- value: 5, name: "pete", bar: 655
- }, options);
- };
你可以調(diào)用該插件而不帶選項,即使用默認配置:
- $("...").foobar();
或者帶一些選項:
- $("...").foobar({ value: 123, bar: 9 });
文檔
如果你發(fā)表你的插件,你應(yīng)該也提供一些例子和文檔。有許多插件可以作為很好的參考。
現(xiàn)在你應(yīng)該具有了寫插件的基本知識。讓我們來寫一個我們自己的插件。
Checkbox插件
很多人使用jQuery來處理表單時會問到radio buttons或checkboxes的checking和unchecking。他們常用這樣的代碼:
- $("input[@type='checkbox']").each(function() {
- this.checked = true;
- this.checked = false; // or, to uncheck
- this.checked = !this.checked; // or, to toggle
- });
無論何時你的代碼里有一個each時,你可能想重寫它為一個插件,非常直接:
- jQuery.fn.check = function() {
- return this.each(function() {
- this.checked = true;
- });
- };
現(xiàn)在該插件可以使用了:
- $("input[@type='checkbox']").check();
現(xiàn)在你也可以為uncheck()和toggleCheck()寫插件了。但是我們通過擴展我們的插件來接收一些選項來替代。
- jQuery.fn.check = function(mode) {
- // if mode is undefined, use 'on' as default
- var mode = mode || 'on';
- return this.each(function() {
- switch(mode) {
- case 'on':
- this.checked = true;
- break;
- case 'off':
- this.checked = false;
- break;
- case 'toggle':
- this.checked = !this.checked;
- break;
- }
- });
- };
我們可以提供選項"on","off"和"toggle"或者默認無選項,例如:
- $("input[@type='checkbox']").check();
- $("input[@type='checkbox']").check('on');
- $("input[@type='checkbox']").check('off');
- $("input[@type='checkbox']").check('toggle');
可選設(shè)置
寫多于一個設(shè)置選項會變得復(fù)雜,因為如果用戶想省略第一個參數(shù)而只使用第二個參數(shù)時他必須傳遞一個null值。
上一節(jié)中對tablesorter的使用證明了使用一個對象來解決這個問題。用戶可以省略所有的參數(shù)或者為每個他想override的設(shè)置傳遞一個具有鍵/值對的對象。
出于練習(xí),你可以嘗試重寫第4節(jié)的Voting代碼為一個插件。插件骨架可能看起來像這樣:
- jQuery.fn.rateMe = function(options) {
- // instead of slecting a static container with
- // $("#rating"), we now use the jQuery context
- var container = this;
- var settings = jQuery.extend({
- url: "rate.php"
- // put more defaults here
- }, options);
- // ... rest of the code ...
- // if possible, return "this" to not break the chain
- return this;
- });
則可以允許你像這樣允許該插件:
- $(...).rateMe({ url: "test.php" });
Next steps
如果你計劃開發(fā)更多的JavaScript,你應(yīng)該考慮稱為FireBug的Firefox插件。它提供一個console(很好的替代alerts),一個debugger和其他有用的stuff來為
JavaScript開發(fā)。
如果你有不能解決的問題、想分享的主意或者只是需要用jQuery表達你的看法,請自由舒暢的post給jQuery mailing list。
對于與本指南相關(guān)的任何東西請在我的blog上post一個comment或者直接聯(lián)系我。
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!