通过该教程,我们将了解到Dojo中的DOM查询以及如何使用dojo/query 模块来选择节点和操作节点。 开始 当使用DOM工作, 最重要是的快速和有效的检索节点。 我们已经讲解了其中的一个do
通过该教程,我们将了解到Dojo中的DOM查询以及如何使用dojo/query 模块来选择节点和操作节点。
开始
当使用DOM工作, 最重要是的快速和有效的检索节点。 我们已经讲解了其中的一个dom.byId. 然而在你的应用程序中,给每一个想要操作的节点提供一个Id是不切实际的任务。 通过Id来查找和操作多个节点也是效率低下的。 幸运的是,dojo还有另外一个解决方案: 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 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"的节点,所以我们需要从数组中取出元素。
通过id来获取节点非常好, 但这并不比使用dom.byId更强大。 可是, query 也允许你通过类名称来选择节点。 比如说,我们想要获得的"odd"类名的节点:
// 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节点来限定查询引擎的范围。
当没有给定第二个参数时, 它会搜索整个DOM结构, 仔细检查<html>下的每个节点。 当指定一个DOM节点为第二个参数时, 查询会只限定在指定的节点和它的子节点。
如果一个DOM非常的小, 比如我们例子, 忽略掉第二个参数还是可以接受。 对于一个DOM结构很大的页面,最好还是设置第二个参数, 相对于访问整个文档,更加快速。
在之后的例子中,我们都会省略掉第二个参数。 但你自己使用query时,请记住上面一段 - 设定第二个参数, 有利于更快的搜索和更好的用户体验。
更多高级选择
我们之前的查询结果混合了<li> 和 <a>, 但如果我们只想检索出<a>标签呢? 你可以混合 标签名和类名:
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", "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, 也称为回调函数, 被每一个数组项调用,参数如下: 第一个为当前的节点, 第二个为节点在数组中的索引, 第三个为正在被遍历的数组. 大部分的开发者, 第三个参数会被忽略; 可是, 在一些例子中, 数组没有被赋值给相关的变量(比如在这个例子里), 那么第三个参数在获得数组中的其它项时非常有用。 forEach方法也接受第二个参数,指定什么范围内可以调用回调函数。
另外的数组辅助函数是给NodeLists 定义的,如map, filter,every和some, 除了every 和some返回一个布尔值外,其它的方法返回一个NodeList.
这里还有几个扩展模块,它们在扩展了NodeLists模块,并添加额外的方法。 Class 和 Style 辅助方法在 dojo/NodeList-dom模块。 dojo/NodeList-dom提供的Dojo中各式各样的DOM方法(addClass,removeClass)。 所以之前的例子可以简单为:
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"); });
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");
另外定义在dojo/NodeList-dom中的方法是 style, toggleClass, replaceClass, place 和 empty. 每一个方法也都会返回一个NodeList:
query(".even").style("color", "white").addClass("italic");
查看例子
事件
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", "dojo/domReady!"], function(query) { query(".hookUp").on("click", function(){ alert("This button is hooked up!"); }); }); </script>
查看Demo
on 方法会依附到每个Node上。