DOJO DOM 功能

In this tutorial, you'll learn about how to use Dojo to manipulate the DOM in a simple, cross-browser way. Using basic DOM knowledge and only a few Dojo functions, you will be able to efficiently create, read, update and delete elements in the page on the fly.

在本教程中,你将学习如何使用DOJO控制DOM节点。使用一些基础的DOM知识和一些DOJO功能,你可以在页面上快捷有效的创建、读取、更新以及删除节点。

Getting Started 开始

As far as browser-based JavaScript is concerned, the Document Object Model (DOM) is the glass that we paint on to put content and user interface in front of our users. If we want to augment, replace or add to the HTML once loaded into the browser, JavaScript and the DOM is how it's done. Dojo aims to make working with the DOM easy and efficient by providing a handful of convenience functions that fill some awkward cross-browser incompatibilities and make common operations simpler and less verbose.

就基于javascript的浏览器而言,文档对象模型(DOM)是我们画在用户界面想展示给用户内容的反应。HTML加载到浏览器之后,如果我们还要修改这些元素,javascript操作DOM就可以做到。DOJO提供了操作DOM的功能,这些功能屏蔽了各不同浏览器之间的差异,并一种更加简单快捷的方式提供给开发者使用。

To explore those functions we will be manipulating a simple page containing an unordered list with five elements in it:

为了解释这些功能,我们将要创建一个简单页面,该页面包含了一个无序ListUI,该UI包含了5个节点元素。

 <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Demo: DOM Functions</title>
<script src="//ajax.googleapis.com/ajax/libs/dojo/1.10.4/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

The page already has the Dojo script tag, and you should recognize the require block. All code that manipulates the DOM must wait until the DOM is ready before it can be executed.

本页面已经包含引用DOJO的脚本标签快,并且你必须能识别出require函数。所有的主要处理代码都需要等DOM加载完毕后,能够被读取后才能够执行。

Retrieval 检索

First things first: We need to know how to get elements from the DOM, in order to work with them. The easiest way to do that is by using the dojo/dom resource's byId method. When you pass an ID to dom.byId, you will receive the DOM node object with that ID. If no matching node is found, a null value will be returned.

我们首先要做的事是:我们需要知道我们如何从DOM上获取节点进而操作他们。最简单的办法就是使用dojo/dom资源的byId函数。当你把节点的ID传递给该函数后,你就可以从DOM获取该ID节点的引用。如果没有该ID的节点元素,函数会返回NULL。

This is the equivalent of using document.getElementById, but with two advantages: it is shorter to type, and it works around some browsers' buggy implementations of getElementById. Another nice feature of dom.byId is that when it is passed a DOM node, it immediately returns that node. This helps to create APIs that take both strings and DOM nodes. Let's look at an example:

这个函数相当于使用了document.getElementById函数。但使用dojo/dom资源的byId函数有两点优势:代码更加简短,并且该函数解决了一些浏览器getElementById函数的一些bug。另外一个优秀的特性是当你传入一个DOM节点时,byId函数会立即返回该节点。这样就可以帮助你可以同时使用字符串和节点对象来创建你的API,下面我们看一个例子。

 // 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"); });

View Demo

The setText function sets the text of a node, but since it passes the node argument to dom.byId it will take either a node ID as a string or a DOM node.

setText函数可以在节点上设置显示的文本。但我们使用的dom的byId函数,所以我们可以以字符串的形式传入节点ID,也可以直接传入DOM的节点对象。

Creation 创建

Another thing you will be doing often is creating elements. Dojo doesn't prevent you from using the native document.createElement method to create elements, but creating the element and setting all the necessary attributes and properties on it can be verbose. Furthermore, there are enough cross-browser quirks to attribute setting to make dojo/dom-construct's create method a more convenient and reliable option.

另一件你经常要做的操作就是创建元素。DOJO并不禁止你使用原生态的document.createElement方法创建元素,但这种创建元素的方法需要设置很多必须的属性,导致代码冗长。有着识别个浏览器差异的DOJO提供了dojo/dom-construct的create方法快捷方便的创建元素。

The arguments to domConstruct.create are as follows: node name as a string, properties of the node as an object, an optional parent or sibling node, and an optional position in reference to the parent or sibling node (which defaults to "last"). It returns the new DOM element node. Let's take a look at an example:

domConstruct.create函数需要的参数如下:节点的名称(字符串类型),节点对象的属性,父节点或者兄弟节点(可选参数),灾父节点或兄弟节点的相对位置(可选参数,默认值为last)。该函数会返回一个新的DOM节点元素。让我们看下下面的例子。

 require(["dojo/dom", "dojo/dom-construct", "dojo/domReady!"],
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"
}
}, list); domConstruct.create("li", {
innerHTML: "Three and a half"
}, three, "after");
});

View Demo

A simple list item is created with the content of "Six" and appended to the list. Next, another list item is created with the content of "Seven", its className property is set to "seven", it's styled so it has a bold font, and then appended to the list. Finally, a list item is created with the contents "Three and a half" and is inserted after the list item with the ID "three".

代码创建了一个内容为Six的列表元素,并添加到了List节点上。下面,另外一个内容为Seven的List item被创建,它的classname为“seven”,样式为字体加粗,然后添加到了列表中。最后一个内容为"Three and a half"的list item被创建,并且添加到ID为three的节点的后面。

When would you create elements explicitly like this, versus setting a container element's innerHTML property? If you already have your content as a string of HTML, setting the innerHTML property will always be faster. However, domConstruct.create comes into its own when you want to create elements but not immediately place them in the DOM, or when you want to insert or append a new element without disturbing the sibling nodes around it.

当你使用这种方式创建一个元素的时候,就可以同时设置容器元素的InnderHtml属性。如果你已经有了string类型的html内容,那么设置innerHtml属性会更快。然后,当你想创建一个元素的时候,使用domConstruct.create 不会立即呈现到DOM中,也无法以父节点和兄弟节点为参考添加或插入新的节点。

Placement 放置

If you already have a node and want to place that node, you will need to use domConstruct.place. The arguments are as follows: a DOM node or string ID of a node to place, a DOM node or string ID of a node to use as a reference, and an optional position as a string which defaults to "last" if not provided. This is very similar to what we saw in domConstruct.create and, in fact, domConstruct.create uses domConstruct.place under the hood. For our example, we have added a few buttons to the page:

如果你已经有了一个节点,想安置他的位置,你需要调用domConstruct.place函数。参数如下:

  • 需要放置的ODM节点对象或者其ID;
  • 需要使用的DOM节点ID或者节点对象引用;
  • 可选参数,位置。默认为last。

这比我们调用domConstruct.create函数简单一些,事实上,domConstruct.createdomConstruct.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>

The example defines functions which move the third node around the list using domConstruct.place:

这个例子定义了一些函数,这些函数主要是在列表中,以多种方式在列表中移动第三个节点。

 require(["dojo/dom", "dojo/dom-construct", "dojo/on", "dojo/domReady!"],
function(dom, 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"),
three = dom.byId("three"); domConstruct.place(three, two, "before");
} function moveAfterFour(){
var four = dom.byId("four"),
three = dom.byId("three"); domConstruct.place(three, four, "after");
} function moveLast(){
var list = dom.byId("list"),
three = dom.byId("three"); domConstruct.place(three, list);
} // Connect the buttons
on(dom.byId("moveFirst"), "click", moveFirst);
on(dom.byId("moveBeforeTwo"), "click", moveBeforeTwo);
on(dom.byId("moveAfterFour"), "click", moveAfterFour);
on(dom.byId("moveLast"), "click", moveLast);
});

View Demo

The possible values for the placement argument are "before", "after", "replace", "only", "first", and "last". Please see the reference guide for domConstruct.place for more details as to what each placement option does, though the names are decently intuitive.

placement参数可以取值"before", "after", "replace", "only", "first", and "last",每个参数的详细意义参考reference guide for domConstruct.place

In the simple case, domConstruct.place does little more than the native parentNode.appendChild(node) might do. Its value is in being able to easily specify position, whether it is in reference to a parent or sibling node - with one consistent API.

在这个简单的例子中domConstruct.place函数做了一些比原生态的parentNode.appendChild(node)更多的一些功能。无论是父节点还是同级节点,使用同一套API就可以比较简单的设置其位置。

Destruction 销毁

Most often you'll be creating nodes, but occasionally, you'll want to remove nodes as well. There are two ways to do this in Dojo: domConstruct.destroy which will destroy a node and all of its children, while domConstruct.empty will only destroy the children of a given node. Both take a DOM node or a string ID of a node as their only argument. We're going to add two more buttons to our page:

大多数据情况下,你都会创建节点,但有时候,你也会想移除节点。在dojo有两种方式可以移除节点:domConstruct.destroy函数,该函数可以销毁节点以及该节点下包含的内容。domConstruct.empty函数则只是销毁该节点下的子节点。在传参数的时候,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"), "click", destroyFirst);
on(dom.byId("destroyAll"), "click", destroyAll);

View Demo

The first button will destroy the first item in the list on each click. The second empties the list entirely.

每次点击第一个按钮,都会把list里面的节点元素的第一个删掉。点击第二个按钮,可以清空List中的节点列表。

Conclusion 总结

So far, we have a pretty comprehensive set of tools that we can use to do simple DOM manipulation, from creating nodes, to moving them about, to getting rid of them -- but they all work on only one node at a time. What if the nodes you want to work with don't have IDs? The next tutorial will cover dojo/query, which allows us to search for and work with nodes based on CSS selectors!

到目前为止,我们有一个非常全面的工具库来操作DOM,创建节点、移动几点或者移除节点---但这些功能都是在一个节点上操作。但如果你想操作的节点上没有ID标识怎么办?下一各教程就是介绍dojo/query模块,该模块可以允许我们通过CSS选择器选择多个节点对象。

上一篇:CSS :hover伪类选择定义和用法


下一篇:模式识别 - 处理多演示样例学习(MIL)特征(matlab)