操作dom时,可以使用dom.byId,缺陷是需要为每一个元素指定唯一ID,是一个可怕的和不切实际的工作。另一个解决方案,采用dojo/query模块。dojo/query使用我们熟悉的css选择器 检索一系列的节点。包括对先进的CSS3 选择器的支持。
1、查询
css/demo.css文件
body {
margin: 0;
padding: 2em;
font-family: Lucida Sans,Lucida Grande,Arial !important;
font-size: 13px !important;
background: white;
color: #333;
}
button {
background-color: #E4F2FF;
background-image: url("//dijit/themes/claro/form/images/buttonEnabled.png");
background-position: center top;
background-repeat: repeat-x;
border: 1px solid #769DC0;
padding: 2px 8px 4px;
font-size:1em;
}
button:hover {
background-color: #AFD9FF;
color: #000000;
}
.add-borders ul {
border: 1px solid red;
padding: 2px;
}
.add-borders li {
border: 1px solid blue;
padding: 2px;
}
.add-borders a {
border: 1px solid black;
padding: 2px;
}
.bold {
font-weight: bold;
}
.italic {
font-style: italic;
}
.highlight {
background-color: yellow;
}
.red {
background-color: red;
}
.blue {
background-color: blue;
}
query.html文件:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Using dojo/query</title>
<link rel="stylesheet" href="css/demo.css">
<script src="dojo/dojo.js" data-dojo-config="async: true"></script>
</head>
<body>
<button class="queryButton">#list</button>
<button class="queryButton">.odd</button>
<button class="queryButton">#list .odd</button>
<button class="queryButton">a.odd</button>
<button class="queryButton">li a</button>
<button class="queryButton">li > a</button>
<button class="queryButton">.italic > a</button>
<div class="add-borders">
<ul id="list" class="">
<li class="odd">
<div class="bold">
<a class="odd">Odd</a>
</div>
</li>
<li class="even">
<div class="italic">
<a class="even highlight">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 highlight">Odd</a>
</div>
</li>
<li class="even">
<a class="even">Even</a>
</li>
</ul>
<ul id="list2">
<li class="odd">Odd</li>
</ul>
</div>
</body>
</html>
事件:
<script>
require(["dojo/query","dojo/NodeList-dom","dojo/domReady!"],
function(query){
function executeSeletor(button){
query(".highlight").removeClass("highlight");
query(button.innerHTML.replace(">",">")).addClass("highlight");
}
query(".queryButton").on("click",function(e){
//console.dir(e);
executeSeletor(e.target);
})
var list = query("#list");
console.dir(list);
});
</script>
使用ID查询:
// 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];
})
"#"标示符告诉query方法去查找拥有此Id属性的节点,与dom.byId功能类似。需要记住的一件事是:query 总是返回一个数组。通过ID抓取节点非常的好,但是他用起来没有 dom.byId强大,但是query允许你使用类名称来选取节点,如果我们只想检索拥有 "odd" 类名称的节点。
// retrieve an array of nodes with the class name "odd"
var odds = query(".odd");
使用"."标示符我们告诉query去查找拥有此类名称属性的节点,将返回一个拥有4个<li>和3个<a>的数组。
2、限制你的查询
// 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结构,使用第二个参数限定你 的查询将更好,通过具体的节点范围询将比在整个文档中查询更加的高效,能提供更好的用户体验。
3、更高级的选择
前面的查询包含了<li>和<a>标签,如果我们只想查询<a>标签要怎么办呢,你可以将一个标签名字和一个类名字合并:
var oddA = query("a.odd");
选择li下所有a元素:
// Retrieve an array of any a element that has an
// li as its ancestor.
var allA = query("li a");
选择li下第一个子元素为a的所有a元素:
// Retrieve an array of any a element that has an
// li as its direct parent.
var someA = query("li > a");
4、节点列表
前面提到query返回符合选择器的一个节点数组,这是一个特殊的数组叫做dojo/NodeList。
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Using dojo/query</title>
<link rel="stylesheet" href="css/demo.css">
<script src="dojo/dojo.js" data-dojo-config="async: true"></script>
<script>
// 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");
});
});
</script>
</head>
<body>
<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>
</body>
</html>
传递给foreach的函数是一个回调函数,被数组中的每个条目所调用,该回调函数包含三个参数:当前的节点,节点的索引,需要迭代的节点列表。
对大多数开发者,第三个参数可以忽略。如果数组未被保存在一个容易访问的变量中,使用第三个参数访问数组中的其他元素很有用的。
dojo/NodeList-dom 提供便利的方法来搭配dojo中的各种dom方法,上面的示例等效于:
<script>
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");
});
</script>
支持链式访问:
样例一:
// Remove "red" from and add "blue" to the className
// of each node matching the selector ".odd"
query(".odd").removeClass("red").addClass("blue");
样例二:
// 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");
5、事件
节点列表提供的另一个便利方法是: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>
