1. 程式人生 > >Dojo 1.6 最新官方教程: 如何使用dojo.query 進行DOM查詢和批量操作

Dojo 1.6 最新官方教程: 如何使用dojo.query 進行DOM查詢和批量操作

在本講義中,我們將學到DOM的查詢,以及如何使用dojo.query來方便的查詢並操作DOM節點。

難度:初學者  適用的Dojo 版本: 1.6

作者: Bryan Forbes

譯者: feijia

入門

對DOM程式設計的一個關鍵要素是能夠快速高效的獲取到你所要使用的節點。之前我們曾經介紹過使用dojo.byId來查詢DOM節點的方法。但是,這種方法的侷限性也很明顯。你很難為頁面上每個節點都起一個唯一的ID;而且通過dojo.byId查詢得到的總是單個節點,當你需要對一組節點做同樣的動作時,dojo.byId 就無能為力了。解決這些侷限的方法就是我們今天將要介紹的:dojo.query 。 dojo.query 方法使用了類似CSS查詢的方式來獲取一組節點,在新版的dojo當中,它甚至已經完全可以支援高階的CSS3 選擇器(selector )了。

常用查詢

為了演示一些最常用的DOM查詢示例,我們假設了如下的一個HTML頁面片段. (這是常見的包含一系列連結的HTML片段)

 

 

針對上述的HTML片段,能想到的第一個操作通常是如何獲取到整個列表的一個控制代碼. 當然你可以用dojo.byId, 但dojo.query 也可以達到同樣目的. 雖然初看起來,你會覺得在這裡dojo.query 不是那麼方便,但結合後面的例子你就會發現它的好處。

 

通過在引數中加入"#", 我們告訴dojo.query 去查詢節點的"ID"屬性。這是從CSS操作中借鑑來的語法。 需要注意的是dojo.query 的返回值永遠是一個數組。 在這個例子中,因為只有一個ID叫"list" 的節點,所以我們直接取出了該陣列的第一個元素。 

上面我們看到了如何通過ID來獲取節點,dojo.query 可不是隻有這麼點能力。它還支援通過class name來選擇節點。假設我們希望能夠獲取所有class name等於"odd" 的節點:

 

通過在引數中加入".", 我們告訴dojo.query 現在是要匹配節點的className屬性, 這也是借鑑了CSS的語法。在這個例子中,dojo.query 將會返回包含4個<li> 節點和3個<a>節點 的陣列。 

限定查詢條件的作用域

你可能已經發現了,在上一個例子中的得到odds陣列同時包含了來自兩個列表的節點。 假設我們只需要獲取第一個列表中的odd節點呢? 有兩種方法

 

這兩種方法返回的都是相同的元素, 第一個方法使用了選擇器的語法,限制了查詢的結果在ID為list的元素內,而第二個方法則將一個節點作為限定查詢引數傳入query。 

當dojo.query 方法不包含第二個引數時,它會搜尋整個DOM樹結構,遍歷<HTML>標籤中包含的每個節點。  如果該方法呼叫時包含了一個DOM節點作為第二引數,這個節點就是查詢的作用域, 查詢的結果一定是該節點或其子節點。

如果你的頁面的DOM樹結構比較小,比如像我們這裡使用的列表的例子,那麼省略第二引數的做法是可以的,也不會過分影響效率。但是如果頁面很複雜,那麼強烈建議你在使用dojo.query是明確指定第二引數來限定查詢的作用域.這會大大減少無謂的對整個頁面進行搜尋操作從而提升速度和效能。

為了方便,在接下來的例子中,我們都會省略第二個引數,不過請你一定要記住:在真實應用中你應該儘可能的制定作用域來讓查詢操作快速高效。

更多高階的查詢

前面的例子中,我們查詢得到的結果集包含了<li> 節點和<a> 節點兩種,如果我們只想要其中的<a> 節點該如何做呢?  在dojo.query 查詢時我們可以將 標籤名和class 名組合作為查詢條件:

 

dojo.query 還支援另一種選擇器, ">".  CSS中使用">" 並不被所有瀏覽器支援,但是在dojo.query中卻可以通用. 

使用這個選擇器,查詢會

 

檢視示例

在我們的例子中,allA會查詢出6個<a>節點,而someA只會包含2個<a>。 在">" 兩側可以使用任意的其他選擇器,包括class 選擇器。這裡我們只是介紹了幾種最常用的選擇器,但dojo.query 是完全相容CSS3的,還能夠支援很多其他的選擇器 .你可以自己進一步學習掌握.

NodeList(操作dojo.query返回的結果集)

前文提到,dojo.query 返回的是匹配查詢結果的所有節點構成的陣列;這個陣列實際上是一個特殊的陣列物件稱為dojo.NodeList, 該陣列物件內建了一系列可以方便操作其中節點的方法. 

下面我們來看一下其中常用的一些方法, 在這個章節我們會使用下面的一個HTML程式碼片段:

 

dojo.NodeList 內建了一些Dojo 陣列輔助方法. 例如forEach, 它可以對陣列中的每個元素執行一個函式:

 

被傳入forEach的函式是一個回撥函式,該回調函式支援3個引數: 當前正在操作的節點,該節點在陣列中的位置序號,以及當前正在遍歷的結果集(是一個dojo.NodeList 物件)

對大多數開發者而言,第三個引數一般用不到, 僅當你在回撥函式中需要去操作結果集中的其他節點時需要用到這個引數. forEach方法還可以接受第二個引數,作為回撥函式呼叫的作用域(Scope)

dojo.NodeList中內建的其他陣列輔助方法還包括: map,filter,every, 和 some. 大多方法都返回一個dojo.NodeList 物件,因此很容易串聯使用. some 和every是例外,它們返回值是布林值(boolean)

dojo.NodeList還內建了一些方面DOM操作的方法, 上一個例子還可以進一步簡化為

 

這些DOM操作方法會在dojo.NodeList中每個節點上執行,同事返回值仍然是一個dojo.NodeList,可以串聯使用.例如

 

其他dojo.NodeList 的DOM操作方法還包括: style, toggleClass,replaceClass, place 和empty. 所有這些方法都會返回dojo.NodeList,供串聯使用.

 

事件

dojo.NodeList 上提供的另一重要方法是connect,用來連線DOM事件. 關於如何在Dojo中處理DOM事件會在下一個講義中詳細討論,我們這裡要解釋一下如何使用dojo.NodeList的connect方法.

特別要注意的是,雖然在dojo.NodeList上使用connect很方便,但是並不適用於dojo.NodeList 包含大量節點的情形, 這種情況下應該使用一種稱為事件代理(event delegation)的技巧.關於這一技巧我們會在未來的講義中探討.

 

上面的例子中我們演示了兩種將dojo.NodeList連線到DOM事件的方法:

通用的connect 方法, 引數中指定事件名稱和回撥函式

使用一系列預定義的onXXXX 方法, 完整的方法列表 可以在參考手冊中查詢

第二種做法更加簡潔一些,但是內建的onXXX方法僅包含了標準的DOM事件, 對於一些非標準事件例如 DOMAttrModified, 則只能使用第一種方法.

小結

利用dojo.query 以及dojo.NodeList,對批量的DOM節點進行操作是很簡單的:

使用dojo.query 查詢到你所需要操作的節點,再使用dojo.NodeList的內建方法對這些節點進行修改操作. 下面一章我們將會進一步介紹如何使用Dojo向頁面中新增互動,如何使用dojo中的事件機制。