3.2 使用dojo/query
原文地址:https://dojotoolkit.org/documentation/tutorials/1.10/using_query/index.html
GitBook地址:https://www.gitbook.com/book/limeng1900/dojo1-11-tutorials-translation-in-chinese/details
轉載請註明出處:http://blog.csdn.net/taijiedi13/ – 碎夢道
本教程中,我們將學習DOM查詢和如何使用dojo/query
來選擇節點。
入門
在使用DOM時,快速和高效地檢索節點很重要。我們已經有了dom.byId
。但是,在應用中用單一的ID來查找所有的興趣節點是不現實的。只用ID在查找和操作多節點時效率也很低。幸好,有另一種解決方案:dojo/query
。dojo/query
模塊使用類CSS查詢(你在樣式表裏使用的)來檢索一個節點列表,它也支持高級的CSS3選擇器。
查詢
我們用下面的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>
第一件要做的事是獲得整個列表的處理器。跟前面一樣,可以用dom.byId
,但你也可以使用query
。初看這個方法不是很有用,但是我們會中這個例子開始講:
// require the query, dom, and domReady modules
require(["dojo/query", "dojo/dom", "dojo/domReady!"], function (query, dom) {
// retrieve an array of nodes with the ID "list"
var list = query("#list")[0];
})
通過前置標識符“#”來告訴query
用ID屬性查找節點。這個規定和CSS相似。記住一件事:query
總是返回一個數組。數組以後再細說,由於這裏通過ID list只得到一個節點(也應該只有一個),就直接從數組取出這個元素。
通過ID獲取節點很棒,但是並沒有比dom.byId
更強大。然而,query
也可以通過類名來選擇節點。我們打算檢索只帶“odd”類的節點:
// retrieve an array of nodes with the class name "odd"
var odds = query(".odd");
我們通過前置“.”的標識符告訴query
查找className屬性中含有該標識的節點,還是和CSS一樣。示例中,query
將返回一個包含4個<li>
和3個<a>
的數組。
限制查詢
你可以已經發現前面的例子中odd
同時包含多個list的節點。如果只想要第一個list的odd節點,可以使用兩種方式:
// retrieve an array of nodes with the class name "odd"
// from the first list using a selector
var odds1 = query("#list .odd");
// retrieve an array of nodes with the class name "odd"
// from the first list using a DOM node
var odds2 = query(".odd", dom.byId("list"));
兩種通過不同的方法實現:第一種使用選擇器語法讓query引擎限制獲取的結果,第二種將query引擎的作用域限制在一個特定的DOM節點。
當query
不帶第二個參數執行的時候,它將搜索全部的DOM結構的全部節點。第二個參數指定爲一個DOM節點時,查詢被限制在該節點和其子節點中。
如果你的DOM相對較小,比如跟例子中一樣,可以省略第二個參數。然而,對於有着更大DOM結構的頁面,最好使用第二個參數來限制query
的作用域。在指定部分執行查詢比搜索全部文檔要快的多。
後面的示例中,我們會省略第二個範圍參數,但是你用query
時要記住前面的話,保持你的檢索快速簡潔來提供更快的代碼和更好的用戶體驗。
進階部分
前面的查詢結果混合了<li>
和<a>
節點,如果只想要<a>
呢?你可以組合標籤名和類名:
var oddA = query("a.odd");
代替分離的標識符,你可以組合標識符來指向更明確的節點;上面的組合類名在跨瀏覽器的樣式表中有不同的效果,不過query
能正常工作。、
query
還有另一個跨瀏覽器的選擇器“>”,但不是全部樣式表都支持。它將只在第一個選擇器下一級查找第二個:
// Retrieve an array of any a element that has an
// li as its ancestor.
var allA = query("li a");
// Retrieve an array of any a element that has an
// li as its direct parent.
var someA = query("li > a");
View Demo
allA
將包含全部的6個<a>
,someA
只有2個<a>
。任何選擇器都可以放在“>”的兩邊,包括類選擇器。這裏我們只涉及幾個常見的選擇器,query
是完全遵循CSS3的,並且可以接受更多選擇器,你可以自己試試。
NodeList
如前面提到的,query
返回一個匹配選擇器的節點數組;這個數組實際上是一個dojo/NodeList
,它還有操作節點的方法。前面的例子已經用了幾個方法,不過我們在看一個你更可能在應用裏用到的。這一系列的示例使用下面的標記:
<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>
NodeList
具備相當於Dojo數組輔助方法的方法。一個是forEach
,會對數組裏每一個節點執行函數:
// Wait for the DOM to be ready before working with it
require(["dojo/query", "dojo/dom-class", "dojo/domReady!"],
function(query, domClass) {
query(".odd").forEach(function(node, index, nodelist){
// for each node in the array returned by query,
// execute the following code
domClass.add(node, "red");
});
});
傳遞給forEach
的函數是一個回調,調用給數組的每一項,參數如下:當前它所在的節點,節點的索引和迭代的NodeList
。對於大部分的開發者,第三個參數可以忽略;但是在數組沒有存儲在變量中的實例中,第三個參數可以用來獲取數組的其他項。forEach
方法也接收第二個參數來指定回調調用的範圍。
NodeList
定義的其他數組幫助函數是map
、filter
、every
和some
。這些函數都返回一個NodeList
,除了every
和some
返回布爾值。
NodeList
還有幾個拓展模塊來添加額外的方法。dojo/NodeList-dom
模塊裏是類和樣式幫助方法。dojo/NodeList-dom
提供對應各種DOM方法的遍歷方法, 這樣前面的例子就可以簡化成:
require(["dojo/query", "dojo/NodeList-dom", "dojo/domReady!"], function(query) {
// Add "red" to the className of each node matching
// the selector ".odd"
query(".odd").addClass("red");
// Add "blue" to the className of each node matching
// the selector ".even"
query(".even").addClass("blue");
});
在NodeList
裏對每個節點執行DOM方法,並且返回一個NodeList
支持鏈接寫法:
// Remove "red" from and add "blue" to the className
// of each node matching the selector ".odd"
query(".odd").removeClass("red").addClass("blue");
dojo/NodeList-dom
定義的其它DOM方法有style
、toggleClass
、 replaceClass
、 place
和empty
。這些方法也都返回一個NodeList
:
// Change the font color to "white" and add "italic" to
// the className of each node matching the selector ".even"
query(".even").style("color", "white").addClass("italic");
事件
NodeList
提供的另一個便利的方法是on
來連接DOM事件。雖然DOM事件將在下一個教程裏涉及,我們會先涉及NodeList
的on
方法的語法。也要記住,雖然這是個方便的語法,這個方式不應該用在包含大量節點的NodeList
,應該用一種叫做事件委託的技術來替代,見事件教程。
<button class="hookUp demoBtn">Click Me!</button>
<button class="hookUp demoBtn">Click Me!</button>
<button class="hookUp demoBtn">Click Me!</button>
<button class="hookUp demoBtn">Click Me!</button>
<script>
// Wait for the DOM to be ready before working with it
require(["dojo/query", "dojo/domReady!"], function(query) {
query(".hookUp").on("click", function(){
alert("This button is hooked up!");
});
});
</script>
on方法附在查詢返回的每一個節點上。
小結
如你所見,大多時候使用DOM節點是很簡單的。使用query
可以快速、輕易地得到想要節點的集合。適應樣式和改變類大多時候很便利,這正是Dojo向頁面添加交互的開始。我們已經展示了一個處理點擊事件的簡單例子,在下一個教程中,我們將深度解析Dojo事件處理。