看完本篇將學會如何使用 dojo.query 來取得節點 (node) 並操作節點。
在使用 DOM 架構的時候,很重要的一點就是要取得 DOM 節點,如此我們才可以指定動作給該節點。在前幾篇我們已經用了 dojo.byId ,由於 Id 是獨一無二的,直接使用 Id 就可以取得某個特定物件。但是當 HTML 架構龐大的時候,把每個物件都指定 Id 或許沒什麼效率,又或者我們需要用到好幾個節點,要一一以 Id 取得節點們實在有點累贅。
這就是為什麼我們需要 dojo.query 。 dojo.query 使用類似於 CSS 的指定方式來取得 DOM 節點。
查詢物件dojo.query
接下來的範例我們要用到下面這段 HTML,這也是網站在建立數個連結時常用的方式:<ul id="list"> <li class="odd"> <div class="bold"> <a class="odd">Odd</a> </div> </li> <li class="even"> <div class="italic"> <a class="even">Even</a> </div> </li> <li class="odd"> <a class="odd">Odd</a> </li> <li class="even"> <div class="bold"> <a class="even">Even</a> </div> </li> <li class="odd"> <div class="italic"> <a class="odd">Odd</a> </div> </li> <li class="even"> <a class="even">Even</a> </li> </ul> <ul id="list2"> <li class="odd">Odd<li> </ul>
首先,我們想要取得 <li> ,然而在這裡 <li> 並沒有設定 Id ,於是我們必須使用 dojo.query 來試試看。
// retrieve an array of nodes with the ID "list" var list = dojo.query("#list")[0];
上列的 JavaScript 中,加上 "#" 代表我們告訴 dojo.query 去找一個符合該 ID 的節點,這就跟 CSS 表示法相同。
要注意一點, dojo.query 的輸出結果一定是一個陣列 (array) 。
不過因為 Id 不會重複,所以我們這樣就得到 "list" 了。
可是 #+ID 並不實用,因為既然有 Id 的話,我們直接用 dojo.byId 就可以了。 dojo.query 真正起作用的地方,就是沒有設定 Id 也可以使用 class 來取得節點物件。下面的範例是我們想要取得 class name 是 "odd" 的物件:
// retrieve an array of nodes with the class name "odd" var odds = dojo.query(".odd");
在變數前加上 "." ,代表我們告訴 dojo.query 去尋找 className 符合該變數的節點物件,這跟 CSS 的表示法也相同,應該很好理解。根據我們上面的範例 HTML 結構,我們應該可以取得4個 <li> 和3個 <a> 。
查詢限制式上面的範例中, class "odd" 同時存在於兩個 <ul> 中,如果我們只想選擇在第一個 <ul>的話,就必須給 dojo.query 的查詢增加一些限制:
// retrieve an array of nodes with the class name "odd" // from the first list using a selector var odds1 = dojo.query("#list .odd"); // retrieve an array of nodes with the class name "odd" // from the first list using a DOM node var odds2 = dojo.query(".odd", dojo.byId("list"));
第一個方法是利用 selector syntax 來從所有節點中限制查詢的結果;第二個方法是藉由縮小查詢的範圍來找到特定的節點。
當沒有指定第二個變數給 dojo.query 的時候,它會從整個 DOM 架構中去查詢,也就是查詢所有在 <html> 之下的節點;如果有指定第二個變數,那麼 dojo.query 就只會從指定的節點和其子節點中去查詢符合的結果。
如果我們的 HTML 文件很小,就像範例這麼短的話,不設定 dojo.query 的第二個變數也沒什麼影響,可是若 HTML 文件很大,最好是設定一下查詢範圍,這樣執行速度較快,使用者的等待時間也能縮短。
更多查詢表示法本篇一開始的範例,得到了包含 <li> 和 <a> 的陣列,如果我們只想要取得 <A>,可以結合 class 名稱 和 tag 名稱。
var oddA = dojo.query("a.odd");
這種結合 class 名稱的用法有時在某些瀏覽器會有問題,不過 dojo.query 已經都處理好了,可以直接使用。
另一種跨瀏覽器可用的表示法是 ">",用法如下。
// 取得一個陣列包括所有在<li> 下層的 <a> var allA = dojo.query("li a"); // 取得一個陣列包括所有直接接在 <li> 下層的 <a> var someA = dojo.query("li > a");
dojo.NodeList
前面有提到,dojo.query 會傳回符合篩選條件的節點組合成的陣列,這個陣列是一個稱為 dojo.NodeList 特殊的陣列,並有一些方法 (method) 可以和陣列中的節點互動。接下來有一些例子,會用到這個結構:
<div id="list"> <div class="odd">One</div> <div class="even">Two</div> <div class="odd">Three</div> <div class="even">Four</div> <div class="odd">Five</div> <div class="even">Six</div> </div>
dojo.NodeList 有和 Dojo array helper methods 相同的方法。其中一個是 forEach,它會使陣列中的所有節點執行某一個函數:
dojo.query(".odd").forEach(function(node, index, nodelist){ // 每一個 dojo.query 傳回的節點 // 都會執行這裡的 code dojo.addClass(node, "red"); });
每當 dojo.query 將傳回值 (callback) 傳進 forEach,就會執行 forEach 中的 function ,這個 function 有三個 input 變數:
- 目前傳回的節點
- 目前節點的索引值 (index)
- 被處理的 dojo.NodeList,也就是 dojo.query 處理過後的結果
forEach 方法可設定第二個參數值來指定一個範圍( scope ),只有符合範圍條件的 dojo.query 的傳回值,才會傳進 forEach。
其他用來處理 dojo.NodeList 的 array function 有 map, filter, every,和 some。
除了 every 和 some 會傳回 boolean ,其他方法都會傳回 dojo.NodeList 以利處理。
另外,Dojo 還有一些方便處理 DOM 的方法,以下的用法可以簡化我們剛才的範例:
// 在符合".odd" 這個篩選條件的節點上 // 加上 className 為 "red" dojo.query(".odd").addClass("red"); // 在符合".even" 這個篩選條件的節點上 // 加上 className 為 "blue" dojo.query(".even").addClass("blue");
這些 DOM 方法,會處理 dojo.NodeList 中每一個節點,並傳回一個 dojo.NodeList:
// 移除符合 ".odd" 的節點的 classNmae "red" // 並加上 className "blue" dojo.query(".odd").removeClass("red").addClass("blue");
還有一些處理 dojo.NodeList 的 DOM 方法為 style, toggleClass, replaceClass, place, and empty。所有這些方法也都回傳回 dojo.NodeList :
// 將 className 符合 ".even" 的節點 // 改變字體顏色為 "white" ,且字型改為 "italic" dojo.query(".even").style("color", "white").addClass("italic");
相關文章---------------
沒有留言:
張貼留言