通过该教程,我们将了解到Dojo中的DOM查询以及如何使用dojo/query 模块来选择节点和操作节点。
开始
当使用DOM工作, 最重要是的快速和有效的检索节点。 我们已经讲解了其中的一个dom.byId. 然而在你的应用程序中,给每一个想要操作的节点提供一个Id是不切实际的任务。 通过Id来查找和操作多个节点也是效率低下的。 幸运的是,dojo还有另外一个解决方案: dojo/query. dojo/query 模块使用css选择器来检索一个节点列表, 它支持CSS3 选择器。
查询
<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>
// require the query and domReady modules require(["dojo/query","dojo/domReady!"],function(query) { // retrieve an array of nodes with the ID "list" var list = query("#list")[0]; })
通过添加一个"#"标识符到 id 的前面, 我们可以告诉 query 通过节点的ID属性寻找节点,它是CSS 的一种约定。 需要注意的是: query 一直返回一个数组。 我们会在之后谈论这个数组, 但由于 仅有一个(而且应该仅有一个)ID为"list"的节点,所以我们需要从数组中取出元素。
// retrieve an array of nodes with the class name "odd" var odds = query(".odd");
通过添加"."前缀,我们告诉query查找节点的className属性。 查找我们例子中的HTML, query 将返回一个包含 4个<li> 元素和3 个<a>元素的数组。
限制性查找
你可能已经注意到, 以上的例子中会检索到两个list中的 odds. 假若我们仅想获得第一个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",document.getElementById("list"));
两个数组包含同样的元素, 但通过了不同的方法: 第一个是使用了选择器语法, 并让选择器引擎从所有的DOM里限定结果, 第二是以指定DOM节点来限定查询引擎的范围。
更多高级选择
var oddA = query("a.odd");
另外一个选择器是 ">",例如:
// 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");查看Demo
allA 变量包含 6 个 <a>标签, 然而 someA仅包含2个<a>标签。 ">"的任何一边可以放置任何选择器, 包括类选择器。 我们在这里仅讲部分常见的选择器,但query是完全支持 CSS3,并接受
更多的选择器
节点列表(NodeList)
之前提到的, query返回一个匹配到的节点数组。 这个数组实际上是一个节点列表对像(dojo/NodeList),NodeList 包含与节点交互的方法。 上一个例子的Demo已经使用了几个这类方法, 但让我们看看在你的应用程序中最常用的几个, 我们使用以下的html标记:
<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",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,也称为回调函数, 被每一个数组项调用,参数如下: 第一个为当前的节点, 第二个为节点在数组中的索引, 第三个为正在被遍历的数组. 大部分的开发者, 第三个参数会被忽略; 可是, 在一些例子中, 数组没有被赋值给相关的变量(比如在这个例子里), 那么第三个参数在获得数组中的其它项时非常有用。 forEach方法也接受第二个参数,指定什么范围内可以调用回调函数。
这里还有几个扩展模块,它们在扩展了NodeLists模块,并添加额外的方法。 Class 和 Style 辅助方法在 dojo/NodeList-dom模块。 dojo/NodeList-dom提供的Dojo中各式各样的DOM方法(addClass,removeClass)。 所以之前的例子可以简单为:
require(["dojo/query","dojo/NodeList-dom",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"); });
DOM 方法会被NodeList中的每一个节点执行, 返回一个为链式调用的NodeList( query(".odd").addClass("red").removeClass("red"),这就是链式调用,链式调用的根本是执行完后需要返回一个NodeList );
// Remove "red" from and add "blue" to the className // of each node matching the selector ".odd" query(".odd").removeClass("red").addClass("blue");
事件
NodeList提供的另外一个遍历方法是on,用来监听DOM事件。 虽然 DOM 事件会在下一个教程中讲解, 我们先讲解 NodeList的on 方法。 在这里应该注意,虽然on方法有方便的方法, 但最好不要用在一个包含大量节点的NodeList上。 而应该使用一用称为 事件委托的技术, 它会在
events tutorial 里讲解.
<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",function(query) { query(".hookUp").on("click",function(){ alert("This button is hooked up!"); }); }); </script>
查看Demo
on 方法会依附到每个Node上。