前言

在上一章中,我们学习了 JavaScript 编程语言。尽管我们开发的程序由 Web 浏览器运行,但是它们与浏览器本身或者浏览器显示的文档之间具有相对很少的交互。在本章中,我们把注意力重点放在 DOM(Document Obicct Model,文档对象模型)上,DOM 是一个API(应用程序编程接口),定义了 JavaScript 程序如何访问和操纵当前由浏览器显示的HTML 文档。 


DOM简介

DOM将整个文档结构抽象成一个树形结构,每个节点都代表着文档中的一个元素、属性或文本节点。通过DOM API,开发者可以访问节点的层次结构,获取或修改节点的属性、内容等信息,也可以插入、移动或删除节点,从而实现动态地操作和更新文档结构。

我们通过一个例子(“Rollover” effect)来看,JavaScript如何通过DOM API来控制文档:

下面的代码实现了:当鼠标没移动到图片上时,展示图片“CFP2.png”;若鼠标移动到图片上时,展示图片“CFP22.png”

//Rollover.html
<html>
  <head>
    <title>Rollover.html</title>
    <script type="text/javascript" src="rollover.js">
    </script>
    <meta http-equiv="Content-Script-Type" content="text/javascript" />
  </head>
  <body>
    <p>
      <img id="img1" src="CFP2.png" alt="flower pot" 
      height="86" width="44"
      onmouseover="swap('img1', 'CFP22.png');"
      onmouseout="swap('img1', 'CFP2.png');" />
    </p>
  </body>
</html>
// rollover.js
function swap(eltId, URL) {
var elt = window.document.getElementById(eltId);
elt.src = URL;
return;
}

我们看到HTML文件中的 meta 标签:<meta http-equiv="Content-Script-Type" content="text/javascript" />

它的作用是告诉浏览器该网页中的脚本类型为 JavaScript。这个标签的内容会被浏览器解析,以便正确地处理网页中的 JavaScript 代码。http-equiv属性被设置为"Content-Script-Type",用于指定HTML文档中内部事件属性的脚本语言。内在事件属性,比如onclickonload,是HTML属性,用于定义在特定事件发生时要执行的JavaScript代码。

对于接下来在img元素中的两个内在事件属性:

onmouseover="swap('img1', 'CFP22.png');"
onmouseout="swap('img1', 'CFP2.png');" />

它们调用了swap()函数,这个函数在JavaScript中。swap()函数的第一个参数为eltID,表示元素的id,用于定位执行函数的具体标签。第二个参数为需要更换的图片的URL,这里是一个相对地址。

在JavaScript中,document.getElementById(eltId)getElementById是DOM API的一部分,它允许开发人员通过文档中元素的ID属性来获取对该元素的引用,意味着这行指令通过ID获取了元素,因为元素ID是唯一的,所以这种方法比传递名字要容易定位。

我们可以看到实际结果是浏览器最初显示相对URL CFP2.png上的图像。当把鼠标移到该图像上时,就会用用位于URL CFP22.png上的图像替换这幅图像。当移开鼠标时,恢复显示原始图像。

DOM技术定义了两个宿主对象(host object),分别是Document宿主对象和Element宿主对象

Document宿主对象提供了访问HTML文档的方法和属性,可以通过该对象获取文档的根节点、head和body等元素,也可以获取文档的title、URL、cookie等信息。开发者可以通过Document对象对整个文档进行操作和控制。

而Element宿主对象则用于访问HTML文档中的元素,包括标签、属性和文本节点等。Element对象提供了一系列的方法和属性,用于获取和修改元素的属性、文本内容、样式等信息,也可以通过Element对象进行事件处理、动态创建和删除元素等操作。

通过这两个宿主对象,开发者可以在JavaScript中轻松地访问和操作HTML文档中的各个元素和节点,实现动态地更新和控制文档内容的效果。


内部事件处理

内部事件(也称为DOM事件)是指在HTML文档中发生的事件,例如用户单击按钮、鼠标滚动、键盘按下等。这些事件是通过DOM技术来实现的,当用户与HTML文档中的元素进行交互时,浏览器会自动触发相应的内部事件。它们可以作为属性放在标签里面。

例如有如下内部事件属性:

像之前的例子一样,无论何时使用一个内部事件属性,还应该在文档的head中包含一个meta元素。一般来讲,meta元素用于指定通常可以在包含HTML文档的响应消息的HTTP头部字段中看到的信息:http-equiv用于指定HTTP头部字段的名称,它的值是content的内容。meta元素定义的特定的HTTP头部字段是Content-Script-Type,它用于为文档内的脚本指定默认的语言;content的内容为"text/javascript"告诉浏览器用JavaScript编写内部事件属性。


修改元素样式

DOM访问通常用于更改HTML文档元素的样式,来响应用户发起的事件。

例如,考虑一个简单的导航栏(navbar)它包含一个链接表格,放在其他内容的左边。使用JavaScript和DOM,当把鼠标移到导航栏中各个项上时,很容易更改它们的外观。

初始状态如图:

我们想要实现的是,当鼠标移动到一项的时候td元素的这一项的背景色为银色,否则为灰色。

这个实现起来和之前的例子差不多,都是使用了两个内部事件onmouseoveronmouseout。下面为td元素的代码:

<td onmouseover="highlight(this);"
    onmouseout="lowlight(this);">
    <a href="http://www.example.org">Products</a>
</td>

当鼠标悬停在该单元格上时,会触发JavaScript函数highlight(),该函数会高亮显示单元格(变银色)。当鼠标移开单元格时,会触发另一个JavaScript函数lowlight(),该函数会取消高亮显示(变灰色)。此时这两个函数的参数为this指针,是当前元素(td)的别名(Reference)。那么我们的JavaScript代码应该写为:

function highlight(element) {
  element.style.backgroundColor = "silver";
  return;
}

代码其中,参数为element是元素实例的一个别名,故我们可以直接使用它。 修改背景,我们只需要修改style属性即可。

对于backgroundColor它实际上是style对象的属性,对应一个CSS样式。这里我们的背景颜色在CSS中应该为:background-color,它带有一个连字符,转换为属性调用的时候我们应该使用驼峰形式命名,即backgroundColor。如果CSS对应的样式没有连字符,那么就保留它原名即可,例如color,转换成属性调用也写作color

当然,上述的函数写法中不包含DOM API的调用,因为我们仅仅是修改了元素属性。下面是使用DOM方法写的lowlight函数。

function lowlight(element) {
  element.style.setProperty("background-color", "gray", "");
  return;
}

setProperty()是一个DOM方法,用于设置CSS属性。它有三个参数:

  1. property:要设置的CSS属性的名称,例如"background-color"。
  2. value:要设置的CSS属性的值,例如"gray"。
  3. priority:可选参数,用于设置CSS属性的优先级。它应该为空字符串或者是“!important
    关键字”

使用setProperty()的好处是可以清晰地设置CSS样式。除此之外,我们还可以增加一个判断,看看当前颜色是不是灰的,例如:

if (element.style.getPropertyValue("background-color") =="gray")

这是使用了DOM的方法,当然也可以用之前的style对象的方法:

if (element.style.backgroundColor == "gray")

后记

本文介绍了DOM(文档对象模型)及其在JavaScript中的应用。DOM将整个文档结构抽象成树形结构,通过DOM API,开发者可以访问和操纵文档中的元素、属性和文本节点,实现动态地操作和更新文档结构。文章以一个例子展示了如何通过DOM API控制文档中的元素,以及内部事件处理的方法。同时解释了使用DOM修改元素样式的过程,通过JavaScript和DOM可以轻松地访问和操作HTML文档中的各个元素和节点,实现动态地更新和控制文档内容的效果。

这里的一切都有始有终,却能容纳所有的不期而遇和久别重逢。
最后更新于 2023-05-17