# Dom 相关基础知识点
TIP
前言: DOM 是 javascript 操作网页的接口,全称为文档对象模型(Document Object Model)。它的作用是将网页转为一个 javascript 对象,从而可以使用 javascript 对网页进行各种操作(比如增删内容)。浏览器会根据 DOM 模型,将 HTML 文档解析成一系列的节点,再由这些节点组成一个树状结构。DOM 的最小组成单位叫做节点(node),文档的树形结构(DOM 树)由 12 种类型的节点组成。本文将主要说明 DOM 节点类型
# 节点类型
# 元素节点
元素节点对应网页的 html 标签元素,节点类型为 1 ,节点名称是大写的标签名,nodeValue 是 null
示例如下
console.log(
document.body.nodeType,
document.body.nodeName,
document.body.nodeValue
); // 1 'BODY' null
console.log(Node.ELEMENT_NODE === 1); // true
# 特性节点
元素特性节点 attribute 对应网页中 HTML 标签的属性,它只存在于元素的 attributes 属性中,并不是 DOM 文档树的一部分。特性节点的节点类型 nodeType 值是 2,节点名称 nodeName 值是属性名,nodeValue 值是属性值。
<div id="demo"></div>;
var attr = demo.attributes.id;
console.log(attr.nodeType, attr.nodeName, attr.nodeValue); // 2 'id' 'test'
console.log(Node.ATTRIBUTE_NODE === 2); // true
# 文本节点
文本节点 text 代表网页中的 HTML 标签内容。文本节点的节点类型 nodeType 值是 3,节点名称 nodeName 值是*#text*,nodeValue 值是标签内容值
<div id="test">测试</div>;
var txt = test.firstChild;
console.log(txt.nodeType, txt.nodeName, txt.nodeValue); //3 '#text' '测试'
console.log(Node.TEXT_NODE === 3); //true
# CDATA 节点
CDATASection 类型只针对基于 XML 的文档,只出现在 XML 文档中,表示的是 CDATA 区域,格式一般为
<![CDATA[
]]>
# 实体引用名称节点
实体是一个声明,指定了在 XML 中取代内容或标记而使用的名称。 实体包含两个部分, 首先,必须使用实体声明将名称绑定到替换内容。 实体声明是使用 <!ENTITY name "value"> 语法在文档类型定义(DTD)或 XML 架构中创建的。其次,在实体声明中定义的名称随后将在 XML 中使用。 在 XML 中使用时,该名称称为实体引用。
实体引用名称节点 entry_reference 的节点类型 nodeType 的值为 5,节点名称 nodeName 的值为实体引用的名称,nodeValue 的值为 null
//实体名称
<!ENTITY publisher "Microsoft Press">
//实体名称引用
<pubinfo>Published by &publisher;</pubinfo>
# 实体名称节点
该节点的节点类型 nodeType 的值为 6,节点名称 nodeName 的值为实体名称,nodeValue 的值为 null
# 处理指令节点
处理指令节点 ProcessingInstruction 的节点类型 nodeType 的值为 7,节点名称 nodeName 的值为 target,nodeValue 的值为 entire content excluding the target
# 注释节点
注释节点 comment 表示网页中的 HTML 注释。注释节点的节点类型 nodeType 的值为 8,节点名称 nodeName 的值为'#comment',nodeValue 的值为注释的内容
<div id="myDiv"><!-- 我是注释内容 --></div>
var com = myDiv.firstChild;
//8 '#comment' '我是注释内容'
console.log(com.nodeType,com.nodeName,com.nodeValue)
console.log(Node.COMMENT_NODE === 8);//true
# 文档节点
文档节点 document 表示 HTML 文档,也称为根节点,指向 document 对象。文档节点的节点类型 nodeType 的值为 9,节点名称 nodeName 的值为'#document',nodeValue 的值为 null
console.log(document.nodeType, document.nodeName, document.nodeValue); // 9 "#document" null
console.log(Node.DOCUMENT_NODE === 9); //true
# 文档类型节点
文档类型节点 DocumentType 包含着与文档的 doctype 有关的所有信息。文档类型节点的节点类型 nodeType 的值为 10,节点名称 nodeName 的值为 doctype 的名称,nodeValue 的值为 null
var nodeDocumentType = document.firstChild;
console.log(
nodeDocumentType.nodeType,
nodeDocumentType.nodeName,
nodeDocumentType.nodeValue
);
console.log(Node.DOCUMENT_TYPE_NODE === 10);
# 文档片段节点
文档片段节点 DocumentFragment 在文档中没有对应的标记,是一种轻量级的文档,可以包含和控制节点,但不会像完整的文档那样占用额外的资源。该节点的节点类型 nodeType 的值为 11,节点名称 nodeName 的值为'#document-fragment',nodeValue 的值为 null
var nodeDocumentFragment = document.createDocumentFragment(); //11
console.log(
nodeDocumentFragment.nodeType,
nodeDocumentFragment.nodeName,
nodeDocumentFragment.nodeValue
); // 11 "#document-fragment" null
console.log(Node.DOCUMENT_FRAGMENT_NODE === 11); //true
# DTD 声明节点
DTD 声明节点 notation 代表 DTD 中声明的符号。该节点的节点类型 nodeType 的值为 12,节点名称 nodeName 的值为符号名称,nodeValue 的值为 null
# 获取节点
说到最常见的 DOM 应用,恐怕就要数取得特定的某个或某组元素的引用了。DOM 定义了许多方式来选取元素,包括 getElementById()、getElementsByTagName()、getElementsByName()和 document.all 4 种。
# getElementById
DANGER
任何 HTML 元素可以有一个 id 属性,在文档中该值必须唯一
[注意]若浏览器中出现多个 id 名的情况,CSS 样式对所有该 id 名的元素都生效,但 javascript 脚本仅对第一个出现该 id 名的元素生效
document.getElementById("xxx"); // 找到则返回该元素,否则返回null
DANGER
关于 getElementById()方法,IE7-浏览器有两个 bug
- 该方法对匹配元素的 ID 不区分大小写
<div id="myDiv" style="height:20px;"></div>;
var div1 = document.getElementById("mydiv");
//在标准浏览器下报错,但在IE7-浏览器下,id为'myDiv'的元素的背景颜色变为品红色
div1.style.backgroundColor = "blue";
- 表单元素的 name 属性也会被当作 ID 属性识别出来。因此为了避免这种问题,最好不让表单元素的 name 属性和其他元素的 ID 属性相同
简写函数 this
var getId = document.getElementById;
console.log(getId.call(document, "div1"));
// 或者
var getId = document.getElementById.bind(document);
# getElementsByTagName()
getElementsByTagName()方法接收一个参数,即要取得元素的标签名,而返回的是包含 0 或多个元素的类数组对象 HTMLCollection。可以使用方括号语法或 item()方法来访问类数组对象中的项,length 属性表示对象中元素的数量
<div>元素一</div>
<div>元素二</div>
var divs = document.getElementsByTagName('div');
divs[0].style.color = 'red';
divs.item(1).style.backgroundColor = 'pink';
# getElementsByName()
getElementsByName()方法会返回带有给定 name 特性的所有元素
DANGER
关于 getElementsByName()方法,IE 浏览器与其他浏览器相比,有三个不同之处
- 【1】IE9-浏览器只支持在表单元素上使用 getElementsByName()方法
- 【2】IE9-浏览器中使用 getElementsByName()方法也会返回 id 属性匹配的元素。因此,不要将 name 和 id 属性设置为相同的值
- 【3】如果对 getElementsByName()方法取得的类数组对象使用 namedItem()方法,因为每一项的 name 属性都相同,所以只会返回第一项 [注意]只有 IE8——IE11 浏览器支持
# document.all
现在 document.all 方法已经弃用,要取得类似效果,可以使用document.getElementsByTagName('*')
方法,*表示匹配所有元素
# getElementsByClassName() H5 新增
HTML 元素的 class 属性值是一个以空格隔开的列表,可以为空或包含多个标识符。在 javascript 中 class 是保留字,所以使用 className 属性来保存 HTML 的 class 属性值
TIP
getElementsByClassName()
方法接收一个参数,即一个包含一个或多个类名的字符串,返回带有指定类的所有元素的类数组对象HTMLCollection
。传入多个类名时,类名的先后顺序不重要。与getElementsByTagName()
类似,该方法既可以用于 HTML 文档对象,也可以用于 element 元素对象
[注意]IE8-浏览器不支持
<ul id="list">
<li class="a ab c">1</li>
<li class="a">2</li>
<li class="ac">3</li>
<li class="a b c">4</li>
<li class="a b">5</li>
</ul>;
//类名中存在a成立
Array.prototype.forEach.call(
list.getElementsByClassName("a"),
(item, index, arr) => {
item.style.fontWeight = "bold";
}
);
//只有类名中同时存在a和c才成立
Array.prototype.forEach.call(
list.getElementsByClassName("a c"),
(item, index, arr) => {
item.style.color = "red";
}
);
TIP
HTML5 为所有元素添加了 classList 属性,这个 classList 属性是新集合类型 DOMTokenList 的实例,它有一个表示自己包含多少元素的 length 属性,而要取得每个元素可以使用 item()方法,也可以使用方括号法
[注意]IE9-浏览器不支持
classList 方法
add(value) 将给定的字符串值添加到列表中,如果值已存在,则不添加
contains(value) 表示列表中是否存在给定的值,如果存在则返回true,否则返回false
remove(value) 从列表中删除给定的字符串
toggle(value) 如果列表中已经存在给定的值,删除它;如果列表中没有给定的值,添加它
<style>
.fc{color: blue;}
</style>
<body>
<div id="test">测试classList</div>
<button id="btn1" onclick = "test.classList.add('fc')">add</button>
<button id="btn2" onclick = "test.classList.contains('fc')?alert(true):alert(false)">contains</button>
<button id="btn3" onclick = "test.classList.remove('fc')">remove</button>
<button id="btn4" onclick = "test.classList.toggle('fc')">toggle</button>
</body>