在这个教程中,你将会学习到在跨浏览器下用Dojo操作 DOM. 使用基本的DOM知识和几个Dojo函数, 你将可以有效的创建,读取,删除一个页面的元素。
开始
就只关注于浏览器端的Javascript,文档对象模型(DOM) 就像一块白纸,我们可以放置内容和用户界面。 如果我们想要扩展(当浏览器加载完页面后,替换和添加新的HTML),就需要做用Javascript来操作DOM。 Dojo 致力于提供一些便利的函数使得DOM操作更加简单而有效,而这些函数是兼容各浏览,操作简单,不冗长。
<!DOCTYPE html> <html> <head> <Meta charset="utf-8"> <title>Demo: DOM Functions</title> <script src="//ajax.googleapis.com/ajax/libs/dojo/1.9.2/dojo/dojo.js" data-dojo-config="async: true"> </script> <script> require(["dojo/domReady!"],function() { }); </script> </head> <body> <ul id="list"> <li id="one">One</li> <li id="two">Two</li> <li id="three">Three</li> <li id="four">Four</li> <li id="five">Five</li> </ul> </body> </html>
这个页面已经有了Dojo Script标签 和 require 代码段。 所有操作DOM的代码必须等DOM已经好后在执行。
检索节点
先说重要的, 我们必须先知道如何从DOM中获得元素, 然后在使用它们。 最简单的是通过dojo/dom的byId方法。 当我们传递了一个ID给dom.byId,你将会接收到一个DOM节点的对象。 如果没有匹配的节点, 会返回一个空值。
这相当于使用 document.getElementById,但相对于有原生的方法,它有两个优势: 一是更短的输入,二是当传入为一个DOM节点时, 会立即返回这个节点。这有助于创建的APIs可以处理字符串和DOM节点。 让我们看一个例子:
// Require the DOM resource require(["dojo/dom","dojo/domReady!"],function(dom) { function setText(node,text){ node = dom.byId(node); node.innerHTML = text; } var one = dom.byId("one"); setText(one,"One has been set"); setText("two","Two has been set as well"); });
查看DEMO
创建节点
你经常会做的另外一件事情是创建一个元素。 Dojo 不会阻止你做用原生的document.createElement方法来创建一个元素, 但通过原生的方法来创建元素和所有必要的参数以及属性会变得很繁琐。此外在设置属性时还会遇到跨浏览器的怪异问题,所以设置属性还是使用dojo/dom-construct的create的方法,更便利和可靠(不用处理浏览器的问题)。
domConstruct.create方法的参数如下: 第一个为字符串作为节点的名称, 第二个为一个对象,作为节点的属性, 第三个为可选的(父节点或同级节点), 第四个为可选的(相对于父节点或同级节点的位置(默认为最后)). 它返回一个新的DOM 元素节点。 让我们来看一个例子:
require(["dojo/dom","dojo/dom-construct",function(dom,domConstruct) { var list = dom.byId("list"),three = dom.byId("three"); domConstruct.create("li",{ innerHTML: "Six" },list); domConstruct.create("li",{ innerHTML: "Seven",className: "seven",style: { fontWeight: "bold" } },{ innerHTML: "Three and a half" },three,"after"); });
查看示例
首先创建了一个内容为 Six的列表项,并将它追加到列表的尾部。 下一步, 创建另一个内容为"Seven" 的列表项,设置类名为 "seven",指它粗字体样式, 然后追加到列表表去。 最后, 内容为" Three and a half"的项会被插入到 ID为”three"列表项的后面。
是使用这种方法来创建一个元素,还是直接设置父元素的innerHTML属性? 如果你已经有了内容,那么设置 innerHTML属性性能上会快一些。 可是,当你想创建的元素不会立即出现在DOM中或当你想插入或者追加的新元素而不会干扰到它周围的同级节点时, 需要使用 domConstruct.create (更细化的控制,直接创建单个的元素,并获得这个元素的引用).
放置元素( Placement)
如果你已经有了一个节点,并想放置它到DOM的哪个位置, 你将需要使用domConstruct.place方法。 它的参数为:第一个参数为想放置的DOM节点,或节点的字符串ID,第二个为参考物的DOM节点或者节点字符串ID. 和一个可选的位置参数(字符串,如果没有提供默认为 "last"). 它跟domConstruct.create很相似, 实际上, domConstruct.create 使用了domConstruct.place引擎(create内部调用了place方法, 以下的例子,我们给一个页面添加了多个按纽。
<button id="moveFirst">The first item</button> <button id="moveBeforeTwo">Before Two</button> <button id="moveAfterFour">After Four</button> <button id="moveLast">The last item</button>
该例子中,我们使用domConstruct.place定义了一个围绕列表来移动第三个节点的功能:
require(["dojo/dom","dojo/on",domConstruct,on){ function moveFirst(){ var list = dom.byId("list"),three = dom.byId("three"); domConstruct.place(three,list,"first"); } function moveBeforeTwo(){ var two = dom.byId("two"),two,"before"); } function moveAfterFour(){ var four = dom.byId("four"),four,"after"); } function moveLast(){ var list = dom.byId("list"),list); } // Connect the buttons on(dom.byId("moveFirst"),"click",moveFirst); on(dom.byId("moveBeforeTwo"),moveBeforeTwo); on(dom.byId("moveAfterFour"),moveAfterFour); on(dom.byId("moveLast"),moveLast); });
查看 DEOM
位置参数可能的值为: "before","after","replace","only","first" 和" last". 可以查看reference guide for comConstruct.place获得更多每个选项的使用。
同样的情况, domConstruct.place 会比原生的parentNode.appendChild (node) 好一些, 它可以简单的指定节点的位置,不论是相对于父节点还是同级节点,都是使用同一个API.
销毁节点(Destruction)
大部分是你会创建节点,但偶尔,你也会删除节点。 Dojo有两个方法用来删除节点: domConstruct.destory 销毁一个节点和它所有的子节点, 而 domConstruct.empty仅销毁给定节点的子节点(给定的节点保留,清空它的内容)。 两个方法都只有一个参数, DOM节点或者字符串ID. 我们续费给页面添加两个按纽:
<button id="destroyFirst">Destroy the first list item</button> <button id="destroyAll">Destroy all list items</button>
function destroyFirst(){ var list = dom.byId("list"),items = list.getElementsByTagName("li"); if(items.length){ domConstruct.destroy(items[0]); } } function destroyAll(){ domConstruct.empty("list"); } // Connect buttons to destroy elements on(dom.byId("destroyFirst"),destroyFirst); on(dom.byId("destroyAll"),destroyAll);
查看Demo
第一个按纽在每次点击时会删除列表中的第一个项, 第二个会清空整个列表。
总结
目前为此, 我们有一个非常全面的工具集使我们可以简单的操作DOM, 从创建节点, 到 移动位置, 在到删除节点。 但每次只能操作一个节点。 假使你有多个节点并且没有Id属性将要怎么操作? 下一教程
dojo/query, 允许我们基于css选择器来查找节点,并对节点进行相关的操作。