操作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",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",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",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",function(query) { query(".hookUp").on("click",function(){ alert("This button is hooked up!"); }); }); </script>