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