DOM 操作
上文中,您已經(jīng)看到如何使用 JavaScript 框架的選擇器和 DOM 遍歷來簡(jiǎn)化特定元素的選取。然而,要想改變 Web 頁面中的特定元素的外觀或內(nèi)容,需要操作 DOM 并應(yīng)用改變。如果使用純 JavaScript 將會(huì)非常繁瑣,幸運(yùn)的是,大多數(shù)JavaScript 框架提供了有用的函數(shù),簡(jiǎn)化了這些操作。
假設(shè)您有一個(gè) div 元素,其 id 是 the-box:
《div id=“the-box”》Message goeshere《/div》
如果要用 jQuery 改變 “Message goes here” 文本,方法如下:
$(‘the-box’).html(‘This is the new message!’);
實(shí)際上,可以在函數(shù)內(nèi)部使用 HTML 代碼,它將由瀏覽器解析。例如:
$(‘the-box’).html(‘This is the 《strong》new《/strong》message!’);
在本例中,div 元素的內(nèi)容在 DOM 中呈現(xiàn)為:
《div id=“the-box”》This is the《strong》new《/strong》 message!《/div》
當(dāng)然,在一些情況下您需要使用特殊字符,如大于號(hào)或小于號(hào)。可以不指定專門的 HTML 實(shí)體代碼,而是使用 jQuery的 text 函數(shù):
$(‘the-box’).text(‘300 》 200’);
這將把 div 元素更新為以下代碼:
《div id=“the-box”》300 》200《/div》
在上面的例子中,原有內(nèi)容被新內(nèi)容取代。如果只是想把消息添加到文本的后面,該怎么做呢?幸好,jQuery 提供了專門的 append 函數(shù):
$(‘the-box’).append(‘, here goes message’);
將這個(gè)函數(shù)應(yīng)用到初始的 div 元素,div 元素的內(nèi)容就變成下面這樣:
《div id=“the-box”》Message goes here, heregoes message《/div》
除了附加以外,您還可以 “前置” 內(nèi)容,即在已有內(nèi)容的前面而不是末尾插入新內(nèi)容。另外,jQuery 提供了在給定元素之外插入內(nèi)容的函數(shù),不管是在開頭還是在末尾。這類函數(shù)可以替換內(nèi)容、清空內(nèi)容、從 DOM 移除所有元素、克隆元素等等。
除了 DOM 操作函數(shù),JavaScript 框架還包含一些用于以編程方式處理元素樣式和 CSS 類的函數(shù)。例如,假設(shè)您有一個(gè)表,您想要在鼠標(biāo)移到某一行時(shí)高亮顯示該行。您創(chuàng)建了一個(gè)特定的名叫 hover 的 CSS 類,并且您想要將這個(gè)類動(dòng)態(tài)添加到行中。在 YUI 中,可以使用以下代碼檢查行中是否已經(jīng)具有 hover 類,如果已經(jīng)有的話,則刪除它,如果沒有的話,則添加它:
if(row.hasClass(‘hover’)) row.removeClass(‘hover’); elserow.addClass(‘hover’);
而且,大多數(shù) JavaScript 框架都有內(nèi)置的 CSS 操作函數(shù)。
?
實(shí)用函數(shù)
很多 JavaScript 框架提供了大量實(shí)用函數(shù),可使 JavaScript 開發(fā)變得很容易。由于這些函數(shù)非常多,因此本文無法一一介紹。我將只討論大多數(shù)框架都具備的一些比較重要的函數(shù)。
如果您曾經(jīng)使用 JavaScript 處理過數(shù)組,你應(yīng)該熟悉使用 for 循環(huán)來遍歷數(shù)組以處理數(shù)組值。例如,看一下清單 2 的代碼:
清單 2. 遍歷 JavaScript 數(shù)組的傳統(tǒng)方法
var fruit = [‘a(chǎn)pple’, ‘banana’, ‘orange’];for(var i = 0;i 《 fruit.length; i++) { alert(fruit[i]);}
清單 2 中的代碼沒有問題,但有些冗長(zhǎng)。大多數(shù) JavaScript 框架包含 each 函數(shù),它會(huì)對(duì)數(shù)據(jù)組的每個(gè)元素調(diào)用一個(gè)指定的函數(shù)。使用 MooTools,可以用清單 3 的代碼執(zhí)行與清單 2 相同的操作。
清單 3. 使用 MooTools 中的 each 函數(shù)
?。邸產(chǎn)pple’, ‘banana’, ‘orange’].each(function(item) {alert(item);});
清單 3 中的語法與 Prototype 和 jQuery 中的語法相同,而與 YUI 和 ExtJS 中的語法有細(xì)微差異。然而,當(dāng)用于 hash映射或?qū)ο蠖皇菙?shù)組時(shí),各框架的語法都不一樣。例如在 MooTools 中,將用到清單 4 的代碼:
清單 4. 在 MooTools 中對(duì)基于鍵/值對(duì)的對(duì)象使用 each
var hash = new Hash({name: “Joe Lennon”, email:“joe@joelennon.ie”});hash.each(function(value, key) { alert(key +“: ” + value);});
在 Prototype 中,將用到清單 5 中的代碼。
清單 5. 在 Prototype 中對(duì)基于鍵/值對(duì)的對(duì)象使用 each
var hash = $H({name: “Joe Lennon”, email:“joe@joelennon.ie”});hash.each(function(pair) { alert(pair.key +“: ” + pair.value);});
每個(gè)框架都包含很多有用的函數(shù),通常劃分為 String 函數(shù)、Number 函數(shù)、Array 函數(shù)、Hash 函數(shù)、Date 函數(shù)等等。更多信息,請(qǐng)查閱相關(guān) JavaScript 框架的 API 參考資料。
?
事件處理
每個(gè) JavaScript 框架都實(shí)現(xiàn)了跨瀏覽器事件處理支持,鼓勵(lì)您從舊式的內(nèi)聯(lián)事件連接轉(zhuǎn)向一種流線化方法??匆幌虑鍐? 中的 jQuery 示例,其中在 hover 事件中高亮顯示 div 元素。
清單 6. 使用 jQuery 連接 hover Event
$(‘the-box’).hover(function() {$(this).addClass(‘highlight’);}, function() {$(this).removeClass(‘highlight’);});
這是一個(gè)由 jQuery 實(shí)現(xiàn)的特殊事件,請(qǐng)注意它有兩個(gè)函數(shù),觸發(fā) onMouseOver 事件時(shí)調(diào)用第一個(gè),觸發(fā) onMouseOut 事件時(shí)調(diào)用第二個(gè)。這是因?yàn)?hover 沒有標(biāo)準(zhǔn)的 DOM 事件。讓我們查看一個(gè)更典型的事件,例如 click(查看清單 7)。
清單 7. 使用 jQuery 連接 click Event
$(‘the-button’).click(function() { alert(‘You pushed thebutton!’);});
如您所見,本例中只有一個(gè)函數(shù)參數(shù)。jQuery 使用這種方式處理大多數(shù) JavaScript 事件。在 jQuery 中使用事件處理函數(shù)時(shí),上下文變量是指觸發(fā)事件的元素。有些框架并不使用這種處理方式。以 Prototype 為例,清單 8 顯示了用 Prototype 實(shí)現(xiàn)的與清單 7 等價(jià)的代碼。
清單 8. 使用 Prototype 連接 click Event
$(‘the-button’).observe(‘click’, function(e) { alert(‘Youpushed the button!’);});
您首先將注意到?jīng)]有 click 函數(shù),而是使用了 observe 函數(shù),該函數(shù)在引用它自身之前將事件作為參數(shù)。您還可能注意到該函數(shù)的參數(shù) e。這就是指向觸發(fā)事件的元素的上下文變量。為了探究其工作原理,讓我們針對(duì) Prototype 重寫 清單6 的代碼(請(qǐng)看清單 9)。
清單 9. 使用 Prototype 連接 hover Event
$(‘the-box’).observe(‘mouseover’, function(e) { var el =Event.element(e); el.addClassName(‘highlight’);});$(‘the-box’).observe(‘mouseout’,function(e) { var el = Event.element(e); el.removeClassName(‘highlight’);});
與 jQuery 中使用美元符號(hào)函數(shù)獲取上下文變量不同的是,在 Prototype 中需要使用 Event.element() 函數(shù)。并且,您需要對(duì) mouseover 和mouseout 使用不同的函數(shù)。
在閱讀本文的過程中,您也許會(huì)注意到函數(shù)使用內(nèi)聯(lián)方式創(chuàng)建且都沒有命名。這意味著它們無法被重用。Prototype 的 hover 例子展示了如何使用已命名的函數(shù)作為替代方法。如清單 10 所示。
清單 10. Prototype 中改進(jìn)的 hover 例子
function toggleClass(e) { var el = Event.element(e);if(el.hasClassName(‘highlight’)) row.removeClassName(‘highlight’); else row.addClassName(‘highlight’);}$(‘the-box’).observe(‘mouseover’,toggleClass);$(‘the-box’).observe(‘mouseout’, toggleClass);
您會(huì)注意到,這次只定義了一個(gè)函數(shù)供 mouseover 和 mouseout 事件調(diào)用。該函數(shù)會(huì)判斷元素是否已經(jīng)高亮顯示了類名,并根據(jù)查找結(jié)果執(zhí)行添加或刪除。您也許會(huì)注意到 e 參數(shù)是隱式傳遞的。換句話說,不需要在 observe 函數(shù)中以參數(shù)形式顯式傳遞事件。
?
Ajax
使用 JavaScript 框架的另一個(gè)有說服力的理由是標(biāo)準(zhǔn)化的跨瀏覽器 Ajax 請(qǐng)求。Ajax 請(qǐng)求是一個(gè)異步 HTTP 請(qǐng)求,通常發(fā)送給服務(wù)器端腳本,后者返回 XML、JSON、HTML 或普通文本格式的響應(yīng)。大多數(shù) JavaScript 框架都有某種形式的Ajax 對(duì)象,以及一個(gè)以參數(shù)形式接受一組選項(xiàng)的請(qǐng)求方法。這些選項(xiàng)通常包含 callback 函數(shù),當(dāng)腳本一接收到來自Web 服務(wù)器的響應(yīng)時(shí),就會(huì)調(diào)用此函數(shù)。讓我們看一下 ExtJS、MooTools 和 Prototype 中的 Ajax 請(qǐng)求的樣子。
首先,看一下典型的 ExtJS Ajax 請(qǐng)求(請(qǐng)看清單 11)。
清單 11. 一個(gè) ExtJS Ajax 請(qǐng)求
Ext.Ajax.request({ url: ‘server_script.php’, params: {name1: ‘value1’, name2: ‘value2’ }, method: ‘POST’, success:function(transport) { alert(transport.responseText); }});
ExtJS 中的 request 方法只有一個(gè)參數(shù),這是一個(gè)包含 url、params、method 和 success 等不同字段的對(duì)象。url 字段包含服務(wù)器端腳本的 URL,該腳本將被 Ajax 請(qǐng)求調(diào)用。params 字段本身就是一個(gè)對(duì)象,包含有將被傳遞給服務(wù)器端腳本的鍵/值對(duì)。method 字段可以取兩個(gè)值:GET 或 POST。它的默認(rèn)值為未定義,但如果請(qǐng)求中有 params,將會(huì)默認(rèn)作為 POST 處理。最后一個(gè)字段 success 是 Web 服務(wù)器返回成功響應(yīng)時(shí)調(diào)用的函數(shù)。在本例中,假設(shè)服務(wù)器端腳本返回普通文本,并且文本會(huì)通過警告框顯示給用戶。
下一步,我們看看同樣的請(qǐng)求在 MooTools 中是什么樣子(請(qǐng)看清單 12)。
清單 12. 一個(gè) MooTools Ajax 請(qǐng)求
new Request({ url: ‘server-script.php’, data: { name1:‘value1’, name2: ‘value2’ }, method: ‘post’, onComplete: function(response) {alert(response); }}).send();
如您所見,MooTools 與 ExtJS 非常相似。你也許注意到,與使用 params 不同,這里使用 data 字段傳遞變量,而且必須使用小寫指定方法。還有,沒有使用 success callback 函數(shù),MooTools 使用了一個(gè) onComplete 函數(shù)。最后,與 ExtJS 不同的是,在 MooTools 中,您需要使用Request 對(duì)象的 send() 函數(shù)發(fā)送請(qǐng)求。
最后,讓我們看看 Prototype 中的請(qǐng)求是否具有顯著的不同(請(qǐng)看清單 13)。
清單 13. 一個(gè) Prototype Ajax 請(qǐng)求
new Ajax.Request(‘server-script.php’, { params: { name1:‘value1’, name2: ‘value2’ }, method: ‘post’, onSuccess: function(transport) {alert(transport.responseText); }});
同樣,Prototype 的工作方式基本一致,只是有些句法上的小差別。首先,Prototype 的 Request 對(duì)象為其構(gòu)造函數(shù)獲取兩個(gè)參數(shù)。第一個(gè)參數(shù)是請(qǐng)求將被發(fā)送到的 URL,第二個(gè)參數(shù)是一個(gè)具有典型 Ajax 選項(xiàng)的對(duì)象,如前兩個(gè)例子所見。當(dāng)然,由于 URL 現(xiàn)在作為單獨(dú)的參數(shù)傳遞,它沒有出現(xiàn)在選項(xiàng)列表中。同樣需要注意,與 MooTools 不同,Prototype Ajax Request 對(duì)象構(gòu)造函數(shù)隱式地發(fā)送請(qǐng)求,因此不需要調(diào)用任何方法來實(shí)際發(fā)起 HTTP 請(qǐng)求。
大多數(shù) JavaScript 框架中的 Ajax 支持要比此處演示的內(nèi)容更加深入。重要的增強(qiáng)功能包括使用接收到的響應(yīng)自動(dòng)更新元素,而不需要任何特殊的 onSuccess 函數(shù)。一些庫(kù)甚至包含預(yù)建的自動(dòng)完成功能,如您在 Google 搜索引擎中所看到的,在輸入時(shí)會(huì)出現(xiàn)常見搜索項(xiàng)。
在下一節(jié)中,您將學(xué)習(xí) JavaScript 框架為 Web 開發(fā)人員提供的用戶體驗(yàn)(UX)增強(qiáng)功能。
?
UX 增強(qiáng)功能
到目前為止,本文全部關(guān)注的是使用 JavaScript 框架的編程優(yōu)勢(shì)以及它們?nèi)绾魏?jiǎn)化交互式應(yīng)用程序的編寫。然而,對(duì)于大多數(shù)框架,還有另外一個(gè)更吸引人的方面:用戶界面(UI)組件以及用戶體驗(yàn)增強(qiáng),這些在以前需要付出很大努力構(gòu)建的工作現(xiàn)在可以輕松完成。
本節(jié)將分別介紹以下框架的 UX 增強(qiáng)功能:Prototype、jQuery、YUI、ExtJS 和 MooTools。
Prototype
Prototype 是少數(shù)幾個(gè)不提供開箱即用 UI 組件和 UX 增強(qiáng)功能的 JavaScript 框架之一。它將這些內(nèi)容轉(zhuǎn)移到其姊妹庫(kù)script.aculo.us(最新版本是 Scripty2)中。Script.aculo.us 還添加了對(duì) Prototype 中的各種效果和行為的支持。包括 highlighting、morphing、folding、shaking、sliding、puffing 等等。Script.aculo.us還提供拖放支持,例如滑塊、in-place Ajax 編輯器和 autocompleters。與其他框架不同,Script.aculo.us 將所有控件(例如滑塊和 autocompleters)的設(shè)計(jì)留給開發(fā)人員,并且未提供標(biāo)準(zhǔn)界面。
jQuery
與 Prototype 不同,jQuery 核心庫(kù)中包含一些基本的 UX 增強(qiáng)。這些增強(qiáng)與script.aculo.us 中的一些基本效果類似。例如 sliding 和 fading。然而,要獲得更高級(jí)的 UX 特性,就需要下載 jQuery UI 庫(kù),它包含比 jQuery 核心庫(kù)更多的效果,以及交互特性,如拖放、調(diào)整大小和排序。與 script.aculo.us 不同的是,jQuery UI 還包含一些小部件或組件,它們使開發(fā)具有吸引力的界面變得更加容易。目前,這些組件包括 Accordion、Datepicker、Dialog、Progressbar、Slider 和 Tabs。這些小部件都可以劃分主題,并且 jQuery UI 包含各種各樣的主題,可以適合您自己的特定 Web 站點(diǎn)或 Web 應(yīng)用程序的組件。圖 1 演示了 jQuery UIDatepicker 小部件的例子,該小部件的主題為 Cupertino。
圖 1. jQuery UI Datepicker Widget
YUI
Prototype 和 jQuery 不包含開箱即用的 UI 小部件,但是 Yahoo! User Interface 庫(kù) (YUI) 包含一個(gè) bucketload。除了支持拖放和調(diào)整大小外,YUI 第二版還包含autocompleters、calendar 控件、carousel 組件、繪圖、對(duì)話框、進(jìn)度條、富文本編輯器(所見即所得文本區(qū))、滑塊、選項(xiàng)卡、樹等等。在撰寫本文時(shí),上述小部件都沒有包含在 YUI 第三版中。圖 2 是結(jié)合使用這些組件的一個(gè)例子。
圖 2. 復(fù)雜的 YUI 應(yīng)用程序示例
ExtJS
和 YUI 一樣,ExtJS 包含大量開箱即用的組件,其中有很多功能強(qiáng)大的網(wǎng)格控件,支持內(nèi)聯(lián)編輯、分頁、篩選、分組、匯總、緩沖和數(shù)據(jù)綁定。ExtJS 組件具有非常專業(yè)的外觀,并且分門別類。其他小部件包括選項(xiàng)卡、圖表、窗口(對(duì)話框)、樹、布局管理器、增強(qiáng)的表單控件、工具欄和菜單、拖放操作和直接遠(yuǎn)程功能(directremoting)。這僅僅是ExtJS 所提供的一小部分,如果要查找更多 RIA 組件,請(qǐng)登錄 ExtJS 網(wǎng)站。圖 3 是用 ExtJS 開發(fā)的 Web 桌面程序示例,展示了這個(gè)庫(kù)的豐富特性。
圖 3. ExtJS 桌面應(yīng)用程序示例
MooTools
MooTools 和 Prototype、jQuery 一樣,也不包含開箱即用的 UI 控件和小部件。與 jQuery 一樣,它包含一組有限的效果。其更高級(jí)的 UX 增強(qiáng)包含在MooTools.More.js 擴(kuò)展中。這個(gè)擴(kuò)展不僅僅是簡(jiǎn)單的 UX/UI 插件,而是包含對(duì) Array、Date、Hash 和 String 類以及額外的 Element 擴(kuò)展的一些有趣的附加功能。至于 UX 增強(qiáng)功能,MooTools.More.js包含拖放支持以及一些其他效果。這些附加功能還包括一些 UI 控件,如 accordion、可排序的HTML 表、scroller、工具提示和 Ajax spinneroverlays。然而,與 script.aculo.us 一樣,您需要自己設(shè)計(jì)這些控件。
?
Framework 比較
表 1 是本文介紹的五個(gè)框架所含特性的詳細(xì)比較。
表 1. 框架特性比較
其他重要框架
限于篇幅,本文只介紹了五個(gè)比較常見的 JavaScript 框架。這并不表示它們是最流行的、最好的或是功能最多的框架。
其他一些 JavaScript 框架也值得注意,包括:
· Cappuccino
· Dojo
· Glow
· GWT
· MochiKit
· Qooxdoo
· Rialto
· Rico
· SproutCore
· Spry
· UIZE
?
結(jié)束語
本文介紹了JavaScript中原型相關(guān)的概念,對(duì)于原型可以歸納出下面一些點(diǎn):
所有的對(duì)象都有“[[prototype]]”屬性(通過__proto__訪問),該屬性對(duì)應(yīng)對(duì)象的原型
所有的函數(shù)對(duì)象都有“prototype”屬性,該屬性的值會(huì)被賦值給該函數(shù)創(chuàng)建的對(duì)象的“__proto__”屬性
所有的原型對(duì)象都有“constructor”屬性,該屬性對(duì)應(yīng)創(chuàng)建所有指向該原型的實(shí)例的構(gòu)造函數(shù)
函數(shù)對(duì)象和原型對(duì)象通過“prototype”和“constructor”屬性進(jìn)行相互關(guān)聯(lián)
還有要強(qiáng)調(diào)的是文章開始的例子,以及通過例子得到的一張“普通對(duì)象”,“函數(shù)對(duì)象”和“原型對(duì)象”之間的關(guān)系圖,當(dāng)你對(duì)原型的關(guān)系迷惑的時(shí)候,就想想這張圖(或者重畫一張當(dāng)前對(duì)象的關(guān)系圖),就可以理清這里面的復(fù)雜關(guān)系了。
通過這些介紹,相信一定可以對(duì)原型有個(gè)清晰的認(rèn)識(shí)。
JavaScript 框架的概念以及它為什么會(huì)給 Web 網(wǎng)站和 Web 應(yīng)用程序開發(fā)帶來好處。本文對(duì)這些框架的常見功能作了簡(jiǎn)要描述,并舉例說明在較常見的庫(kù)中如何實(shí)現(xiàn)這些特性。本文還分別講解了作為這五個(gè)框架的一部分或作為單獨(dú)的附加功能的 UI 和 UX 增強(qiáng)。最后,還提供了一個(gè)直觀的特性對(duì)比圖表,其中列出了各個(gè)框架各自具備和缺乏的選項(xiàng)。有了這些知識(shí),您應(yīng)該就可以進(jìn)行更深入的研究,然后明智地選擇適合您及您的開發(fā)團(tuán)隊(duì)的框架。
評(píng)論
查看更多