还好我们有另一个解决方案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(["dojo/query", "dojo/domReady!"], function(query) {
// retrieve an array of nodes with the ID "list"
var list = query("#list")[0];
})
预先设置一个
"#"标示符 我们将告诉
query
方法去查找 拥有此Id属性的节点,此用法与css的用法非常的相近。需要记住的一件事是:query 总是返回一个数组
通过ID抓取节点非常的好,但是他用起来没有
dom.byId
强大,但是query
允许你使用类名称来选取节点,如果我们只想检索拥有 "odd" 类名称的节点。
// retrieve an array of nodes with the class name "odd"
var odds = query(".odd");
使用
"."标示符 我们告诉
query 去查找拥有此类名称属性 的节点,这特别的像css 使用我们的例子 将返回一个 拥有 4个 <li>
和 3 <a>
的数组。
限制你的查询
你也许注意到 dom的每个列表中都存在 odds
,如果我们想从第一个列表中的到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上
当query
不使用第二个参数执行时,他将在整个DOM结构中查找,查询<html>标签下的每个有效的节点。当一个DOM节点被指定为第二个参数,将限定query 到此节点及其子节点上。
如果你的DOM相当的小省略第二个参数是可接受的,如果一个页面很大的DOM结构,使用第二个参数限定你 的查询将更好,通过具体的节点范围询将比在整个文档中查询更加的高效。能提供更好的用户体验。
更高级的选择
前面的查询包含了<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 ancestor.
var someA = query("li > a");
allA
将会包含六个<a> someA将包含两个<a>任何选择器都可以在">" 的一边,包括类选择器,在这里我们只是包含了一些常用的选择器但是query 是支持全部的CSS3 选择器,而且可以接受更多的选择器。
节点列表
前面提到 query返回 符合选择器的一个节点数组。这是一个特殊的数组叫做 节点列表,有方法处理包含在其内的节点。
下面我们介绍一下其中的一些方法。
使用下面标记:
<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>
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
方法也接收第二个参数 指出毁掉函数 被调用的执行环境上下文。
另外的节点列表数组帮助方法是 map、 filter
、every、some
除了 every、some 返回布尔值外其他的 都返回一个容易连接的节点列表。
dojo 1.7 已经将类和样式帮助移动到了 dojo/NodeList-dom 资源
dojo/NodeList-dom 提供便利的方法来搭配dojo中的各种 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");
});
dom 方法被每个节点列表中的节点所执行,返回一个容易连接的节点
// Remove "red" from and add "blue" to the className
// of each node matching the selector ".odd"
query(".odd").removeClass("red").addClass("blue");
事件
节点列表提供的另一个便利方法是:on 连接到DOM 事件
需要注意的是 虽然这是一个 便利的格式,但是这种方法不应该应用在一个包含大量的节点的一个节点列表上,
在这种情况下我们将使用事件委托
<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 方法将被连接到 query 放法返回的所有节点上。
结论
正如你所见操作大量的Dom 节点时是相当的简单。
使用query我们能够快速并且简单的得到我们想要操作的节点集合,能够调整样式和类是相当的简单。
dojo 的闪光之处是为页面带来了 交互。