20110428

Dojo DOM Functions - dojo.query

看完本篇將學會如何使用 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 處理過後的結果
通常不會用到第三個變數,除非在某些情況下陣列( dojo.NodeList )中的變數不易取得,就可以透過第三個變數。

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");



相關文章---------------

Dojo DOM Functions -(下)

Dojo DOM Functions -(上)

Dojo Modules 模組化管理

Dojo Toolkit 1.6 - Hello Dojo! Hello World

Dojo Toolkit 1.6 First Peep

沒有留言:

張貼留言