如何用DOM-2生成动态内容1

最近出现的对等网络分布式计算,以及人们对实时数据交换重新燃起的兴趣,已经使在 web 上显示动态内容这个热门话题烟消云散了。遗憾的是,HTTP 的无态性和不同浏览器中渲染构件的局限性,给希望把新鲜的信息传递给客户端而又不想向服务器端发送额外请求的 web 开发者们带来了重大的挑战。

为了应对这个挑战,开发者回退到 JavaScript 技巧的使用上来,比如巧妙地使用 document.write() 语句,frameset,以及 IFRAME,或者使用 Internet Explorer 的 innerHTML()insertAdjacentHTML() 函数来插入新的HTML内容,这种状态一直延续到最近。这些方法虽然在某种程度上是成功的,但是通常都和特定的浏览器实现互相耦合。这些技术的一个具体的缺陷就是很少把文档的结构作为一个问题来考虑。在绝大多数情况下,只是把一个又一个的 HTML 字符串简单地插入到页面上,很少考虑实际上正在渲染的是什么内容。

幸运的是,随着遵循 W3 的浏览器的出现,我们现在可以有更好的方法。被 IE5 和 NS6 两种浏览器所支持的二级文档对象模型(Document Object Model Level 2,即 DOM-2)提供了一种接口,使得开发人员可以在页面装载完成之后即时生成新的 HTML。通过调用 DOM-2 方法,可以创建 HTML 元素,定义元素的属性,并把元素附加到文档或者现有的元素中,从而实现HTML的即时生成。本文将探讨 DOM-2 中用于在浏览器中生成动态内容的一些基本功能。

本文假定您对正确的文档结构有一个一般的认识,并且把文档的概念理解为一系列聚合在一起的具有父子关系的HTML对象。

结点和元素

DOM-2 规范中把构成一个文档的所有项目都称为结点。结点接口提供了一系列公共的方法和属性,使得开发者可以访问和操作文档中的所有项目。

和 NS6(Mozilla)一样,IE5 把 HTML 文档中的所有项目或者识别为元素,或者识别为文本结点。理解元素和文本结点的基本差别是非常重要的。元素普遍地和由尖括号包围起来的标识相关联。在 HTML,所有的标识都是元素,比如 <P>,<IMG> 和 <DIV>。元素也可能有属性,或者包含子结点。

另一方面,文本结点代表一块文本。它和元素不同,没有属性或者子结点(虽然它从结点接口中继承了 childNodes 和属性集合)。

考虑下面的例子代码:

<span id="weather">Partly cloudy, scattered showers, high 67</span>

上面的代码由两个独立的结点组成。<SPAN >标识是一个元素结点,带有一个ID属性。在 SPAN 中间的文本实际上是一个独立的文本结点。这个结点只有文本,没有属性或者子结点。

元素结点和文本结点存在一些共同的属性:

  • nodeType:这个属性保存一个数字值,对应于结点的类型。元素的 nodeType 属性值为 1,而文本结点的 nodeType 属性值为 3。在操作中如果需要考察几个未知类型结点,则可以用这个属性来区分特定的结点类型。
  • nodeName:这个属性保存一个字符串。和 nodeType 一样,这个字符串和结点的类型相对应。所有的文本结点的 nodeName 属性值都为“#text”。对于元素,其 nodeName 属性值包含元素标识的名字。因此一个 HTML image 标识的 nodeName 属性值为“IMG”。
  • nodeValue:这个属性保存结点的值,如果有的话。元素的 nodeValue 属性值为 null。文本结点的 nodeValue值 是该结点包含的实际文本字符串。

如果您需要结点属性和方法的完整列表,可以参考 W3C 的 DOM-2 规范

创建元素和文本

文档对象中包含的一系列方法,使新结点的创建成为可能。这些方法是:

  • createElement(String type):创建指定类型的新元素,并返回该元素的一个引用。
  • createTextNode(String text):以text参数指定的内容创建一个新的文本结点,并返回该结点的一个引用。

createElement

创建一个新的元素结点出乎意料的简单。只要调用 createElement 方法,并传入您希望的元素类型就可以了。如果您希望对这个新建的元素执行进一步的操作,则把该方法的返回值--即这个新建元素的引用--赋值给一个变量将是一个很好的主意。

下面的代码创建了一个新的没有内容的段落元素:

 var newPara = document.createElement("p"); 

现在 newPara 变量就是该新建段落元素的一个引用。

createTextNode

您可以用类似的方式创建文本结点,即调用 createTextNode 方法,传入希望放入这个新建结点的文本字符串。和创建元素时一样,您可以把返回值保存到一个变量中,以便在随后的代码中引用。

 var newText = document.createTextNode("This is a new sentence."); 

前面的代码创建了两个新的结点,但是这两个结点在浏览器中不能看到,因为它们还没有被插入到文档中。新建的结点将自由地浮在 JavaScript 中,直到您把它们分配给一个父亲对象,或者文档体(body)对象的本身。

从结点接口继承下来的每一个对象都有一个名为 appendChild 的方法,这个方法使其它结点可以被插入到本结点。举例来说,通过使用 appendChild 方法,您可以把 newText 这个新的文本结点插入到名为 newPara 的段落元素中:

var newPara = document.createElement("p");
var newText = document.createTextNode("This is a new sentence.");
newPara.appendChild(newText);

现在,您需要做的,就是把段落元素插入到文档体对象中。为了实现这个目的,您需要得到文档的BODY元素的一个引用。有几种方法可以获得这个引用。多数比较新的浏览器版本(IE5 和 NS6)都允许您使用 document.body 语句,比如 document.body.appendChild(newPara);,然而这是一个非标准的便利属性,在未来版本中可能不能工作。

一个更加遵循标准的方法是通过文档对象的 getElementsByTagName 方法来获得文档中可以找到的第一个 BODY 元素的引用。

var bodyRef = document.getElementsByTagName("body").item(0);
bodyRef.appendChild(newPara);

方法 item(0) 是必要的,因为 getElementsByTagName 函数返回的是其根据指定标识名称找到的元素的集合。由于一个 HTML 页面中通常只有一个 BODY 标识,所以您可以直接使用 item 方法从集合中取得第一项。

还有一个遵循标准的方法可以用来获取文档体的引用,就是使用 getElementById 方法。然而,这个方法假定您已经不怕麻烦,为您的 HTML 页面的 <BODY> 标识分配了一个ID属性。

<body id="docBody">
var bodyRef = document.getElementById("docBody");
bodyRef.appendChild(newPara);

您也可以使用 getElementsByTagName getElementById 这两个方法来得到除了文档体对象之外的其它页面对象的引用。例如,点击这个连接就会激活一个脚本,该脚本使用 getElementById 方法来获得本文当前这个段落元素的引用(这个段落元素的 ID 属性被指定为“example1”),然后通过 appendChild 方法向这个段落元素中插入一个新的文本结点。

完成上述任务的代码如下所示:

<script type="text/javascript">
function insertNewText()
{
var newText = document.createTextNode
	(" DOM方法很酷,不是吗?");
var para = document.getElementById("example1");
para.appendChild(newText);
}
</script>
<script type=text/javascript> function insertNewText(){ var newText = document.createTextNode("DOM方法真酷,不是吗?"); var para = document.getElementById("example1"); para.appendChild(newText); } </script>

由于 ID 属性值为“example1”的段落元素已经存在于文档的 BODY 元素中,所以完全没有必要去引用文档体对象了。这是一个简单的例子,但是这个例子表现出来的概念可以用来进行其它复杂的DOM操作。

在创建新结点时有一些限制:一个是新创建的结点只能被插入到创建这个结点的文档中。这意味着如果您使用一系列的帧,则您不能在一个帧中创建一个元素,然后添加到另一个帧的文档对象中。还有,把一个元素从一个窗口传递到另外一个窗口也是不可能的。

还有一点值得一提,就是您也受限于文档的逻辑层次以及当前正在操作的结点类型。如果试着把一个节点插入到该结点本身或该结点自己的子结点,或者插入到不允许把该类型的结点作为子结点的其它结点对象中,则可能会出现错误。

在什么地方使用 innerHTML?

您可能会奇怪,为什么我们要用这些看起来很复杂的,很冗长的 JavaScript 语句来创建那么一点文本或者一个 HTML 元素?您完全可以使用 innerHTML 来完成这些工作呀。

innerHTML 是 Microsoft 公司作为读写一个元素的 HTML 内容而引入的便利属性。举例来说,通过 innerHTML 语句,您可以轻松创建一个具有多个格子的表结构,并将它插入到您的页面中:

var str = '<table border="1">';
str += '<tr><td>Cell One</td><td>Cell Two?	</td><td>Cell Three</td></tr>';
str += '</table>';
document.all["paragraphOne"].innerHTML = str;

innerHTML 已经被集成到 Mozilla 的代码库中,而且现在也是 NS6 的一部分了。因此我们为什么不用它呢?一个基本的原因就是 innerHTML 并不返回其创建的结点的任何引用。如果由于某些原因,需要修改这个新表的第二个TD元素中的文本,那您就没有办法找到第二个格子的引用了--而如果使用 createElement() 函数的话,则我们当时就已经拥有这个引用了,因为该函数总是返回结点的引用。您可以用 document.all,或者甚至是使用 document.getElementById() 函数来得到相应结点的引用,但是这些方法假定您已经为字符串中的每一个元素都正确地分配了唯一的 ID。如果是这样的话,重新书写整个字符串,并再次插入到 paragraphOne 对象中可能更容易一些。

您选择什么方法最终取决于您希望完成什么任务。如果您只是简单地显示文本或者 HTML,不需要访问新创建的元素,那就使用 innerHTML。然而,如果您计划在一个大一些的动态生成结构中对特定的对象进行操作,则需要花一些时间,通过 DOM 文档方法来进行对象的构造。

更多的结点操作

同添加新结点一样,您也可以移除现有的结点。removeChild 方法使得任何结点可以移除它自己的子结点,只要简单地传入您希望移除的结点的引用就可以了。在被移除的结点中的任何元素或者文本也将一起被移除。

当B元素被从段落中移除时,在这些黑体标识之间的文本,也会一起消失。

<script type="text/javascript">
function removeBElm(){
var para = document.getElementById("example2");
var boldElm = document.getElementById("example2B");
var removed = para.removeChild(boldElm);
} </script>
<script type=text/javascript> function removeBElm(){ var para = document.getElementById("example2"); var boldElm = document.getElementById("example2B"); var removed = para.removeChild(boldElm); } </script>

点击这个连接看看上面的脚本是如何动作的。

被移除的结点并没有被破坏。removeChild 函数会返回被移除的结点的引用,因此随后可以对这个结点进行其它的操作。请注意,在这个例子中我们把被移除的B元素赋值给 removed 变量,从而维护了该结点的一个引用。

如果您想要移除一个不存在的结点,或者一个被标注为只读的结点,则可能回出现错误,这取决于浏览器的实现。

代替结点

除了移除结点之外,DOM还提供了一个把一个结点代替为另一个结点的方法。replaceChild 方法就可以实现这个功能。和上面的 removeChild 方法一样,replaceChild 函数必须由包含希望被代替的结点的元素进行调用。

replaceChild 接收两个参数:一个是新结点的引用,另一个是即将被代替的结点的引用。下面的例子创建一个包含一个文本节点的新 SPAN 元素,并用它来代替现有的SPAN元素。

<script type="text/javascript">
function replaceSpan(){

var newSpan = document.createElement("span");
var newText = 
	document.createTextNode("受惊的斑马");
newSpan.appendChild(newText);

var para = document.getElementById("example3");
var spanElm = document.getElementById("ex3Span");
var replaced = para.replaceChild(newSpan,spanElm);
}
</script>

您可以在这个试一下这个例子:

敏捷的棕色狐狸在懒惰的狗上跳跃。

<script type=text/javascript> function replaceSpan(){ var newSpan = document.createElement("span"); var newText = document.createTextNode("受惊的斑马"); newSpan.appendChild(newText); var para = document.getElementById("example3"); var spanElm = document.getElementById("ex3Span"); var replaced = para.replaceChild(newSpan,spanElm); } </script>

在一个结点系列中插入

您可能已经注意到,在先前的例子中,appendChild 函数总是把新添加的结点作为父结点的最后一个子结点。在某些时候,可能需要在现有结点之前或者之间插入结点。

insertBefore 这个结点方法可以实现这个目的。insertBefore 接收两个参数:即将被插入的新结点,以及您希望在哪个结点之前插入。下面的例子用 insertBefore 方法在 HTML 表格中的一个现有的 TD 前插入一个新的TD元素。

<table border="1">
	<tr id="example4">
		<td>TD One</td>
		<td>TD Two</td>
		<td>TD Three</td>
	</tr>
</table>

<script type="text/javascript">

var TDCount = 0;

function insertTD(){

	var newTD = document.createElement("td");
	var newText = document.createTextNode("New Cell " + (TDCount++));
	newTD.appendChild(newText);

	var trElm = document.getElementById("example4");
	var refTD = trElm.getElementsByTagName("td").item(2);
	trElm.insertBefore(newTD,refTD);
	
}
</script>

您可以在这里试一个这个例子:

TD OneTD TwoTD Three
<script type=text/javascript> var TDCount = 0; function insertTD(){ var newTD = document.createElement("td"); var newText = document.createTextNode("New Cell " + (TDCount++)); newTD.appendChild(newText); var trElm = document.getElementById("example4"); var refTD = trElm.getElementsByTagName("td").item(2); trElm.insertBefore(newTD,refTD); } </script>

前面的路

我们已经讨论了 DOM-2 如何使 HTML 的即时生成和页面操作变成如此的简单,然而您可能还需要更强大的功能。本文没有讨论如何影响元素的属性,比如表格的格子宽度,背景颜色等等。在下一篇文章中,您将会看到如何用DOM-2来操作元素的属性,以及创建动态效果,您还将看到其它一些结点的方法和属性,以及为了更方便地引用 DOM 树中对象而提供的元素接口。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用JavaScriptDOM文档对象模型)来动态生成HTML内容。具体而言,可以通过JavaScript代码创建新的HTML元素,并将它们添加到现有的HTML文档中。以下是一个简单的示例,演示如何使用DOM动态生成HTML内容: ```html <!DOCTYPE html> <html> <head> <title>动态生成HTML内容示例</title> </head> <body> <h1 id="title"></h1> <p id="content"></p> <script> var title = "动态生成HTML内容"; var content = "这是一个使用JavaScript DOM动态生成HTML内容的示例。"; // 创建新的HTML元素 var titleElement = document.createElement("h1"); var contentElement = document.createElement("p"); // 设置元素属性和内容 titleElement.setAttribute("id", "title"); titleElement.innerHTML = title; contentElement.setAttribute("id", "content"); contentElement.innerHTML = content; // 将元素添加到现有的HTML文档中 document.body.appendChild(titleElement); document.body.appendChild(contentElement); </script> </body> </html> ``` 在这个例子中,我们首先在HTML页面中定义了两个`<h1>`和`<p>`标签,分别用于显示标题和内容。然后,在JavaScript代码中,我们定义了两个变量`title`和`content`,用于存储标题和内容的文本。接下来,我们使用`document.createElement()`方法创建了两个新的HTML元素`titleElement`和`contentElement`。然后,我们使用`setAttribute()`方法设置了元素的属性`id`,并使用`innerHTML`属性设置了元素的内容。最后,我们使用`appendChild()`方法将新元素添加到现有的HTML文档中。运行该代码后,将动态生成一个带有标题和内容HTML页面。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值