通过 HTML DOM,JavaScript 能够访问和改变 HTML 文档的所有元素。
一、HTML DOM(文档对象模型)
当网页被加载时,浏览器会创建页面的文档对象模型(Document Object Model)。
1、什么是 DOM?
DOM 是一项 W3C (World Wide Web Consortium) 标准。
DOM 定义了访问文档的标准:
“W3C 文档对象模型(DOM)是中立于平台和语言的接口,它允许程序和脚本动态地访问、更新文档的内容、结构和样式。”
W3C DOM 标准被分为 3 个不同的部分:
- Core DOM - 所有文档类型的标准模型
- XML DOM - XML 文档的标准模型
- HTML DOM - HTML 文档的标准模型
2、什么是 HTML DOM?
HTML DOM 是 HTML 的标准对象模型和编程接口。它定义了:
- 作为对象的 HTML 元素
- 所有 HTML 元素的属性
- 访问所有 HTML 元素的方法
- 所有 HTML 元素的事件
换言之:HTML DOM 是关于如何获取、更改、添加或删除 HTML 元素的标准。
3、对象的 HTML DOM 树
HTML DOM 模型被结构化为对象树:

通过这个对象模型,JavaScript 获得创建动态 HTML 的所有力量:
- JavaScript 能改变页面中的所有 HTML 元素
- JavaScript 能改变页面中的所有 HTML 属性
- JavaScript 能改变页面中的所有 CSS 样式
- JavaScript 能删除已有的 HTML 元素和属性
- JavaScript 能添加新的 HTML 元素和属性
- JavaScript 能对页面中所有已有的 HTML 事件作出反应
- JavaScript 能在页面中创建新的 HTML 事件
通过 HTML DOM,树中的所有节点均可通过 JavaScript 进行访问。所有 HTML 元素(节点)均可被修改,也可以创建或删除节点。
4、节点父、子和同胞
节点树中的节点彼此拥有层级关系。
父(parent)、子(child)和同胞(sibling)等术语用于描述这些关系。父节点拥有子节点。同级的子节点被称为同胞(兄弟或姐妹)。
- 在节点树中,顶端节点被称为根(root)
- 每个节点都有父节点、除了根(它没有父节点)
- 一个节点可拥有任意数量的子
- 同胞是拥有相同父节点的节点
下面的图片展示了节点树的一部分,以及节点之间的关系:
<html> <head> <title>DOM 教程</title> </head> <body> <h1>DOM 第一课</h1> <p>Hello world!</p> </body> </html>
从以上的 HTML 中您能读到以下信息:
- <html> 是根节点
- <html> 没有父
- <html> 是 <head> 和 <body> 的父
- <head> 是 <html> 的第一个子
- <body> 是 <html> 的最后一个子
同时:
- <head> 有一个子:<title>
- <title> 有一个子(文本节点):"DOM 教程"
- <body> 有两个子:<h1> 和 <p>
- <h1> 有一个子:"DOM 第一课"
- <p> 有一个子:"Hello world!"
- <h1> 和 <p> 是同胞
二、HTML DOM Document 对象
每个载入浏览器的 HTML 文档都会成为 Document 对象。
描述当前窗口或指定窗口对象的文档。它包含了文档从<head>到</body>的内容。
用法:
document (当前窗口)
或 <窗口对象>.document (指定窗口)
Document 对象使我们可以从脚本中对 HTML 页面中的所有元素进行访问。
1、Document 对象集合
- all[]:提供对文档中所有 HTML 元素的访问。
- anchors[]:返回对文档中所有 Anchor 对象的引用。
- applets:返回对文档中所有 Applet 对象的引用。
- forms[]:返回对文档中所有 Form 对象引用。
- images[]:返回对文档中所有 Image 对象引用。
- links[]:返回对文档中所有 Area 和 Link 对象引用。
document.images[] 是一个数组,包含了文档中所有的图片(<img>)。要引用单个图片,可以用 document.images[x]。如果某图片包含“name”属性,也就是用“<img name="...">”这种格式定义了一幅图片,就可以使用“document.images['...']”这种方法来引用图片。在 IE 中,如果某图片包含 ID 属性,也就是用“<img id="...">”这种格式定义了一幅图片,就可以直接使用“<imageID>”来引用图片。
单个 Image 对象的属性:name; src; lowsrc; width; height; vspace; hspace; border 这些属性跟<img>标记里的同名属性是一样的。在 Netscape 里,除了 src 属性,其它属性(几乎全部)都不能改的,即使改了,在文档中也不能显示出效果来。这些属性最有用的就是 src 了,通过对 src 属性赋值,可以实时的更改图片。
事件:onclick
不显示在文档中的 Image 对象是用 var 语句定义的:
var myImage = new Image(); 或
var myImage = new Image(<图片地址字符串>);
然后就可以像一般 Image 对象一样对待 myImage 变量了。不过既然它不显示在文档中,以下属性:lowsrc, width, height, vspace, hspace, border 就没有什么用途了。一般这种对象只有一个用:预读图片(preload)。因为当对对象的 src 属性赋值的时候,整个文档的读取、JavaScript 的运行都暂停,让浏览器专心的读取图片。预读图片以后,浏览器的缓存里就有了图片的 Copy,到真正要把图片放到文档中的时候,图片就可以立刻显示了。现在的网页中经常会有一些图像连接,当鼠标指向它的时候,图像换成另外一幅图像,它们都是先预读图像的。
预读图像的 JavaScript 例子
以下例子适合预读少量图片。
var imagePreload = new Image(); imagePreload.src = '001.gif'; imagePreload.src = '002.gif'; imagePreload.src = '003.gif';
以下例子适合预读大量图片。
function imagePreload() { var imgPreload = new Image(); for (i = 0; i < arguments.length; i++) { imgPreload.src = arguments[i]; } } imagePreload('001.gif', '002.gif', '003.gif', '004.gif', '005.gif');
2、Document 对象属性
- body:提供对 <body> 元素的直接访问。对于定义了框架集的文档,该属性引用最外层的 <frameset>。
- cookie:设置或返回与当前文档有关的所有 cookie。
- domain:返回当前文档的域名。
- lastModified:返回文档被最后修改的日期和时间。
- referrer:返回载入当前文档的文档的 URL。
- title:返回当前文档的标题。
- URL:返回当前文档的 URL。
- fgColor :指<body>标记的 text 属性所表示的文本颜色。
- bgColor :指<body>标记的 bgcolor 属性所表示的背景颜色。
- linkColor :指<body>标记的 link 属性所表示的连接颜色。
- alinkColor :指<body>标记的 alink 属性所表示的活动连接颜色。
- vlinkColor :指<body>标记的 vlink 属性所表示的已访问连接颜色
3、Document 对象方法
- getElementById():返回对拥有指定 id 的第一个对象的引用。
- getElementsByName():返回带有指定名称的对象集合。
- getElementsByTagName():返回带有指定标签名的对象集合。
- open():打开一个流,以收集来自任何 document.write() 或 document.writeln() 方法的输出。
- write():向文档写 HTML 表达式 或 JavaScript 代码。
- writeln():等同于 write() 方法,不同的是在每个表达式之后写一个换行符。
- close():关闭用 document.open() 方法打开的输出流,并显示选定的数据。
- clear() :清空当前文档。
open方法实例:弹出式更新通知:
var whatsNew = open('','_blank','top=50,left=50,width=200,height=300,' + 'menubar=no,toolbar=no,directories=no,location=no,' + 'status=no,resizable=no,scrollbars=yes'); whatsNew.document.write('<center><b>更新通知</b>< /center>'); whatsNew.document.write('<p>最后更新日期:00.08.01'); whatsNew.document.write('<p>00.08.01:增加了“我的最爱”栏目。'); whatsNew.document.write('<p align="right">' + '<a href="javascript:self.close()">关闭窗口</a>'); whatsNew.document.close();
当然也可以先写好一个 HTML 文件,在 open() 方法中直接 load 这个文件。
三、查找 HTML 元素
首个 HTML DOM Level 1 (1998),定义了 11 个 HTML 对象、对象集合和属性。它们在 HTML5 中仍然有效。
后来,在 HTML DOM Level 3,加入了更多对象、集合和属性。
- document.anchors:返回拥有 name 属性的所有 <a> 元素。
- document.baseURI:返回文档的绝对基准 URI
- document.body:返回 <body> 元素
- document.cookie:返回文档的 cookie
- document.doctype:返回文档的 doctype
- document.documentElement:返回 <html> 元素
- document.documentMode:返回浏览器使用的模式
- document.documentURI:返回文档的 URI
- document.domain:返回文档服务器的域名
- document.embeds:返回所有 <embed> 元素
- document.forms:返回所有 <form> 元素
- document.head:返回 <head> 元素
- document.images:返回所有 <img> 元素
- document.implementation:返回 DOM 实现
- document.inputEncoding:返回文档的编码(字符集)
- document.lastModified:返回文档更新的日期和时间
- document.links:返回拥有 href 属性的所有 <area> 和 <a> 元素
- document.readyState:返回文档的(加载)状态
- document.referrer:返回引用的 URI(链接文档)
- document.scripts:返回所有 <script> 元素
- document.strictErrorChecking:返回是否强制执行错误检查
- document.title:返回 <title> 元素
- document.URL:返回文档的完整 URL
通常,通过 JavaScript,您需要操作 HTML 元素。
1、通过 HTML 对象选择器查找 HTML 对象
本例查找 id="frm1" 的 form 元素,在 forms 集合中,然后显示所有元素值:
var x = document.forms["frm1"]; var text = ""; var i; for (i = 0; i < x.length; i++) { text += x.elements[i].value + "<br>"; } document.getElementById("demo").innerHTML = text;
以下 HTML 对象(和对象集合)也是可访问的:
- document.anchors
- document.body
- document.documentElement
- document.embeds
- document.forms
- document.head
- document.images
- document.links
- document.scripts
- document.title
2、通过 id 查找 HTML 元素
在 DOM 中查找 HTML 元素的最简单的方法,是通过使用元素的 id。
本例查找 id="intro" 元素:
var x=document.getElementById("intro");
如果找到该元素,则该方法将以对象(在 x 中)的形式返回该元素。
如果未找到该元素,则 x 将包含 null。
3、通过标签名查找 HTML 元素
本例查找 id="main" 的元素,然后查找 id="main" 元素中的所有 <p> 元素:
var x=document.getElementById("main"); var y=x.getElementsByTagName("p");
4、通过类名找到 HTML 元素
本例通过 getElementsByClassName 函数来查找 class="intro" 的元素:
var x=document.getElementsByClassName("intro");
5、通过 CSS 选择器查找 HTML 元素
如果您需要查找匹配指定 CSS 选择器(id、类名、类型、属性、属性值等等)的所有 HTML 元素,请使用 querySelectorAll() 方法。
本例返回 class="intro" 的所有 <p> 元素列表:
var x = document.querySelectorAll("p.intro");
querySelectorAll() 不适用于 Internet Explorer 8 及其更早版本。
四、DOM - 导航
1、导航节点关系
通过 JavaScript,您可以使用以下节点属性在节点之间导航:
- parentNode
- childNodes[nodenumber]
- firstChild
- lastChild
- nextSibling
- previousSibling
<html> <body> <p>Hello World!</p> <div> <p>DOM 很有用!</p> <p>本例演示节点关系。</p> </div> </body> </html>
firstChild 属性可用于访问元素的文本:
<html> <body> <p id="intro">Hello World!</p> <script> x=document.getElementById("intro"); document.write(x.firstChild.nodeValue); </script> </body> </html>
2、DOM 根节点
这里有两个特殊的属性,可以访问全部文档:
- document.documentElement - 全部文档
- document.body - 文档的主体
<html> <body> <p>Hello World!</p> <div> <p>DOM 很有用!</p> <p>本例演示 <b>document.body</b> 属性。</p> </div> <script> alert(document.body.innerHTML); </script> </body> </html>
3、子节点和节点值
文本节点的值能够通过节点的 innerHTML 属性进行访问:
var myTitle = document.getElementById("demo").innerHTML;
访问 innerHTML 属性等同于访问首个子节点的 nodeValue:
var myTitle = document.getElementById("demo").firstChild.nodeValue;
也可以这样访问第一个子节点:
var myTitle = document.getElementById("demo").childNodes[0].nodeValue;
以下三个例子取回 <h1> 元素的文本并复制到 <p> 元素中:
document.getElementById("id02").innerHTML = document.getElementById("id01").innerHTML; document.getElementById("id02").innerHTML = document.getElementById("id01").firstChild.nodeValue; document.getElementById("id02").innerHTML = document.getElementById("id01").childNodes[0].nodeValue;
4、nodeName 属性
nodeName 属性规定节点的名称。
- nodeName 是只读的
- 元素节点的 nodeName 等同于标签名
- 属性节点的 nodeName 是属性名称
- 文本节点的 nodeName 总是 #text
- 文档节点的 nodeName 总是 #document
<h1 id="id01">我的第一张网页</h1> <p id="id02">Hello!</p> <script> document.getElementById("id02").innerHTML = document.getElementById("id01").nodeName; </script>
注释:nodeName 总是包含 HTML 元素的大写标签名。
5、nodeValue 属性
nodeValue 属性规定节点的值。
- 元素节点的 nodeValue 是 undefined
- 文本节点的 nodeValue 是文本文本
- 属性节点的 nodeValue 是属性值
6、nodeType 属性
nodeType 属性返回节点的类型。nodeType 是只读的。
<h1 id="id01">我的第一张网页</h1> <p id="id02">Hello!</p> <script> document.getElementById("id02").innerHTML = document.getElementById("id01").nodeType; </script>
最重要的 nodeType 属性和类型是:
- ELEMENT_NODE:1
- ATTRIBUTE_NODE:2
- TEXT_NODE:3
- COMMENT_NODE:8
- DOCUMENT_NODE:9
- DOCUMENT_TYPE_NODE:10
Type 2 在 HTML DOM 中已弃用。XML DOM 中未弃用。
五、改变 HTML 元素的内容
改变 HTML 元素
- element.innerHTML = new html content:改变元素的 inner HTML
- element.attribute = new value:改变 HTML 元素的属性值
- element.setAttribute(attribute, value):改变 HTML 元素的属性值
- element.style.property = new style:改变 HTML 元素的样式
1、改变 HTML 输出流
JavaScript 能够创建动态的 HTML 内容:
今天的日期是: Fri Feb 21 2020 16:34:17 GMT+0800 (中国标准时间)
在 JavaScript 中,document.write() 可用于直接向 HTML 输出流写内容。
<!DOCTYPE html> <html> <body> <script> document.write(Date()); </script> </body> </html>
注意:绝对不要在文档(DOM)加载完成之后使用 document.write()。这会覆盖该文档。
2、改变 HTML 内容
修改 HTML 内容的最简单的方法是使用 innerHTML 属性。
如需改变 HTML 元素的内容,请使用这个语法:
document.getElementById(id).innerHTML=新的 HTML
本例改变了 <p>元素的内容:
<html> <body> <p id="p1">Hello World!</p> <script> document.getElementById("p1").innerHTML="新文本!"; </script> </body> </html>
本例改变了 <h1> 元素的内容:
<!DOCTYPE html> <html> <body> <h1 id="header">Old Header</h1> <script> var element=document.getElementById("header"); element.innerHTML="新标题"; </script> </body> </html>
3、改变 HTML 属性
如需改变 HTML 元素的属性,请使用这个语法:
document.getElementById(id).attribute=新属性值
本例改变了 <img> 元素的 src 属性:
<!DOCTYPE html> <html> <body> <img id="image" src="smiley.gif"> <script> document.getElementById("image").src="landscape.jpg"; </script> </body> </html>
4、改变 HTML 样式
如需改变 HTML 元素的样式,请使用这个语法:
document.getElementById(id).style.property=新样式
下面的例子会改变 <p> 元素的样式:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>菜鸟教程(runoob.com)</title> </head> <body> <p id="p1">Hello World!</p> <p id="p2">Hello World!</p> <script> document.getElementById("p2").style.color="blue"; document.getElementById("p2").style.fontFamily="Arial"; document.getElementById("p2").style.fontSize="larger"; </script> <p>以上段落通过脚本修改。</p> </body> </html>
本例改变了 id="id1" 的 HTML 元素的样式,当用户点击按钮时:
<!DOCTYPE html> <html> <body> <h1 id="id1">我的标题 1</h1> <button type="button" onclick="document.getElementById('id1').style.color='red'"> 点我!</button> </body> </html>
六、添加和移除HTML元素(节点)
添加和删除元素
- document.createElement(element):创建 HTML 元素
- document.removeChild(element):删除 HTML 元素
- document.appendChild(element):添加 HTML 元素
- document.replaceChild(element):替换 HTML 元素
- document.write(text):写入 HTML 输出流
1、创建新的 HTML 元素 (节点) - appendChild()
要创建新的 HTML 元素 (节点)需要先创建一个元素,然后在已存在的元素中添加它。
<div id="div1"> <p id="p1">这是一个段落。</p> <p id="p2">这是另外一个段落。</p> </div> <script> var para = document.createElement("p"); var node = document.createTextNode("这是一个新的段落。"); para.appendChild(node); var element = document.getElementById("div1"); element.appendChild(para); </script>
2、创建新的 HTML 元素 (节点) - insertBefore()
以上的实例我们使用了 appendChild() 方法,它用于添加新元素到尾部。
如果我们需要将新元素添加到开始位置,可以使用 insertBefore() 方法:
<div id="div1"> <p id="p1">这是一个段落。</p> <p id="p2">这是另外一个段落。</p> </div> <script> var para = document.createElement("p"); var node = document.createTextNode("这是一个新的段落。"); para.appendChild(node); var element = document.getElementById("div1"); var child = document.getElementById("p1"); element.insertBefore(para, child); </script>
3、移除已存在的元素
要移除一个元素,你需要知道该元素的父元素。
<div id="div1"> <p id="p1">这是一个段落。</p> <p id="p2">这是另外一个段落。</p> </div> <script> var parent = document.getElementById("div1"); var child = document.getElementById("p1"); parent.removeChild(child); </script>
注意:早期的 Internet Explorer 浏览器不支持 node.remove() 方法。
注意:如果能够在不引用父元素的情况下删除某个元素,就太好了。不过很遗憾。DOM 需要清楚您需要删除的元素,以及它的父元素。
以下代码是已知要查找的子元素,然后查找其父元素,再删除这个子元素(删除节点必须知道父节点):
var child = document.getElementById("p1"); child.parentNode.removeChild(child);
4、替换 HTML 元素 - replaceChild()
我们可以使用 replaceChild() 方法来替换 HTML DOM 中的元素。
<div id="div1"> <p id="p1">这是一个段落。</p> <p id="p2">这是另外一个段落。</p> </div> <script> var para = document.createElement("p"); var node = document.createTextNode("这是一个新的段落。"); para.appendChild(node); var parent = document.getElementById("div1"); var child = document.getElementById("p1"); parent.replaceChild(para, child); </script>
七、HTML DOM 集合
1、HTMLCollection 对象
getElementsByTagName() 方法返回 HTMLCollection 对象。
HTMLCollection 对象是类数组的 HTML 元素列表(集合)。
下面的代码选取文档中的所有 <p> 元素:
var x = document.getElementsByTagName("p");
该集合中的元素可通过索引号进行访问。
如需访问第二个 <p> 元素,您可以这样写:
y = x[1];
注释:索引从 0 开始。
2、HTML HTMLCollection 长度
length 属性定义了 HTMLCollection 中元素的数量:
var myCollection = document.getElementsByTagName("p"); document.getElementById("demo").innerHTML = myCollection.length;
length 属性在您需要遍历集合中元素时是有用的:
改变所有 <p> 元素的背景色:
var myCollection = document.getElementsByTagName("p"); var i; for (i = 0; i < myCollection.length; i++) { myCollection[i].style.backgroundColor = "red"; }
注意:HTMLCollection 也许看起来像数组,但并非数组。
您能够遍历列表并通过数字引用元素(就像数组那样)。
不过,您无法对 HTMLCollection 使用数组方法,比如 valueOf()、pop()、push() 或 join()。
八、HTML DOM 节点列表NodeList
NodeList 对象是一个从文档中获取的节点列表 (集合) 。
NodeList 对象类似 HTMLCollection 对象。
一些旧版本浏览器中的方法(如:getElementsByClassName())返回的是 NodeList 对象,而不是 HTMLCollection 对象。
所有浏览器的 childNodes 属性返回的是 NodeList 对象。
大部分浏览器的 querySelectorAll() 返回 NodeList 对象。
以下代码选取了文档中所有的 <p> 节点:
var myNodeList = document.querySelectorAll("p");
NodeList 中的元素可以通过索引(以 0 为起始位置)来访问。
访问第二个 <p> 元素可以是以下代码:
y = myNodeList[1];
1、NodeList 对象 length 属性
NodeList 对象 length 属性定义了节点列表中元素的数量。
var myNodelist = document.querySelectorAll("p"); document.getElementById("demo").innerHTML = myNodelist.length;
修改节点列表中所有 <p> 元素的背景颜色:
var myNodelist = document.querySelectorAll("p"); var i; for (i = 0; i < myNodelist.length; i++) { myNodelist[i].style.backgroundColor = "red"; }
2、HTMLCollection 与 NodeList 的区别
HTMLCollection 是 HTML 元素的集合,NodeList 是一个文档节点的集合。
NodeList 与 HTMLCollection 都与数组对象有点类似,可以使用索引 (0, 1, 2, 3, 4, ...) 来获取元素。
NodeList 与 HTMLCollection 都有 length 属性。都不是一个数组!
HTMLCollection 元素可以通过 name,id 或索引来获取。NodeList 只能通过索引来获取。
只有 NodeList 对象有包含属性节点和文本节点。