17 【Document 节点】
# 17 【Document 节点】
# 1.Document 节点的概述
document节点对象代表整个文档,每张网页都有自己的document对象。window.document属性就指向这个对象。只要浏览器开始载入 HTML 文档,该对象就存在了,可以直接使用。
document对象有不同的办法可以获取。
- 正常的网页,直接使用
document或window.document。 iframe框架里面的网页,使用iframe节点的contentDocument属性。- Ajax 操作返回的文档,使用
XMLHttpRequest对象的responseXML属性。 - 内部节点的
ownerDocument属性。
document对象继承了EventTarget接口和Node接口,并且混入(mixin)了ParentNode接口。这意味着,这些接口的方法都可以在document对象上调用。除此之外,document对象还有很多自己的属性和方法。
# 2.Document 节点的属性
# 2.1 快捷方式属性
以下属性是指向文档内部的某个节点的快捷方式。
(1)document.defaultView
document.defaultView属性返回document对象所属的window对象。如果当前文档不属于window对象,该属性返回null。
document.defaultView === window // true
(2)document.doctype
对于 HTML 文档来说,document对象一般有两个子节点。第一个子节点是document.doctype,指向<DOCTYPE>节点,即文档类型(Document Type Declaration,简写DTD)节点。HTML 的文档类型节点,一般写成<!DOCTYPE html>。如果网页没有声明 DTD,该属性返回null。
var doctype = document.doctype;
doctype // "<!DOCTYPE html>"
doctype.name // "html"
2
3
document.firstChild通常就返回这个节点。
(3)document.documentElement
document.documentElement属性返回当前文档的根元素节点(root)。它通常是document节点的第二个子节点,紧跟在document.doctype节点后面。HTML网页的该属性,一般是<html>节点。
(4)document.body,document.head
document.body属性指向<body>节点,document.head属性指向<head>节点。
这两个属性总是存在的,如果网页源码里面省略了<head>或<body>,浏览器会自动创建。另外,这两个属性是可写的,如果改写它们的值,相当于移除所有子节点。
(5)document.scrollingElement
document.scrollingElement属性返回文档的滚动元素。也就是说,当文档整体滚动时,到底是哪个元素在滚动。
标准模式下,这个属性返回的文档的根元素document.documentElement(即<html>)。兼容(quirk)模式下,返回的是<body>元素,如果该元素不存在,返回null。
// 页面滚动到浏览器顶部
document.scrollingElement.scrollTop = 0;
2
(6)document.activeElement
document.activeElement属性返回获得当前焦点(focus)的 DOM 元素。通常,这个属性返回的是<input>、<textarea>、<select>等表单元素,如果当前没有焦点元素,返回<body>元素或null。
(7)document.fullscreenElement
document.fullscreenElement属性返回当前以全屏状态展示的 DOM 元素。如果不是全屏状态,该属性返回null。
if (document.fullscreenElement.nodeName == 'VIDEO') {
console.log('全屏播放视频');
}
2
3
上面代码中,通过document.fullscreenElement可以知道<video>元素有没有处在全屏状态,从而判断用户行为。
# 2.2 节点集合属性
以下属性返回一个HTMLCollection实例,表示文档内部特定元素的集合。这些集合都是动态的,原节点有任何变化,立刻会反映在集合中。
(1)document.links
document.links属性返回当前文档所有设定了href属性的<a>及<area>节点。
// 打印文档所有的链接
var links = document.links;
for(var i = 0; i < links.length; i++) {
console.log(links[i]);
}
2
3
4
5
(2)document.forms
document.forms属性返回所有<form>表单节点。
var selectForm = document.forms[0];
上面代码获取文档第一个表单。
除了使用位置序号,id属性和name属性也可以用来引用表单。
/* HTML 代码如下
<form name="foo" id="bar"></form>
*/
document.forms[0] === document.forms.foo // true
document.forms.bar === document.forms.foo // true
2
3
4
5
(3)document.images
document.images属性返回页面所有<img>图片节点。
var imglist = document.images;
for(var i = 0; i < imglist.length; i++) {
if (imglist[i].src === 'banner.gif') {
// ...
}
}
2
3
4
5
6
7
上面代码在所有img标签中,寻找某张图片。
(4)document.embeds,document.plugins
document.embeds属性和document.plugins属性,都返回所有<embed>节点。
(5)document.scripts
document.scripts属性返回所有<script>节点。
var scripts = document.scripts;
if (scripts.length !== 0 ) {
console.log('当前网页有脚本');
}
2
3
4
(6)document.styleSheets
document.styleSheets属性返回网页内嵌或引入的 CSS 样式表集合。
(7)小结
除了document.styleSheets属性,以上的其他集合属性返回的都是HTMLCollection实例。document.styleSheets属性返回的是StyleSheetList实例。
document.links instanceof HTMLCollection // true
document.images instanceof HTMLCollection // true
document.forms instanceof HTMLCollection // true
document.embeds instanceof HTMLCollection // true
document.scripts instanceof HTMLCollection // true
2
3
4
5
HTMLCollection实例是类似数组的对象,所以上面这些属性都有length属性,都可以使用方括号运算符引用成员。如果成员有id或name属性,还可以用这两个属性的值,在HTMLCollection实例上引用到这个成员。
// HTML 代码如下
// <form name="myForm">
document.myForm === document.forms.myForm // true
2
3
# 2.3 文档静态信息属性
以下属性返回文档信息。
(1)document.documentURI,document.URL
document.documentURI属性和document.URL属性都返回一个字符串,表示当前文档的网址。不同之处是它们继承自不同的接口,documentURI继承自Document接口,可用于所有文档;URL继承自HTMLDocument接口,只能用于 HTML 文档。
document.URL
// http://www.example.com/about
document.documentURI === document.URL
// true
2
3
4
5
如果文档的锚点(#anchor)变化,这两个属性都会跟着变化。
(2)document.domain
document.domain属性返回当前文档的域名,不包含协议和端口。比如,网页的网址是http://www.example.com:80/hello.html,那么document.domain属性就等于www.example.com。如果无法获取域名,该属性返回null。
document.domain基本上是一个只读属性,只有一种情况除外。次级域名的网页,可以把document.domain设为对应的上级域名。比如,当前域名是a.sub.example.com,则document.domain属性可以设置为sub.example.com,也可以设为example.com。修改后,document.domain相同的两个网页,可以读取对方的资源,比如设置的 Cookie。
另外,设置document.domain会导致端口被改成null。因此,如果通过设置document.domain来进行通信,双方网页都必须设置这个值,才能保证端口相同。
(3)document.location
Location对象是浏览器提供的原生对象,提供 URL 相关的信息和操作方法。通过window.location和document.location属性,可以拿到这个对象。
(4)document.lastModified
document.lastModified属性返回一个字符串,表示当前文档最后修改的时间。不同浏览器的返回值,日期格式是不一样的。
document.lastModified
// "03/07/2018 11:18:27"
2
注意,document.lastModified属性的值是字符串,所以不能直接用来比较。Date.parse方法将其转为Date实例,才能比较两个网页。
var lastVisitedDate = Date.parse('01/01/2018');
if (Date.parse(document.lastModified) > lastVisitedDate) {
console.log('网页已经变更');
}
2
3
4
如果页面上有 JavaScript 生成的内容,document.lastModified属性返回的总是当前时间。
(5)document.title
document.title属性返回当前文档的标题。默认情况下,返回<title>节点的值。但是该属性是可写的,一旦被修改,就返回修改后的值。
document.title = '新标题';
document.title // "新标题"
2
(6)document.characterSet
document.characterSet属性返回当前文档的编码,比如UTF-8、ISO-8859-1等等。
(7)document.referrer
document.referrer属性返回一个字符串,表示当前文档的访问者来自哪里。
document.referrer
// "https://example.com/path"
2
如果无法获取来源,或者用户直接键入网址而不是从其他网页点击进入,document.referrer返回一个空字符串。
document.referrer的值,总是与 HTTP 头信息的Referer字段保持一致。但是,document.referrer的拼写有两个r,而头信息的Referer字段只有一个r。
(8)document.dir
document.dir返回一个字符串,表示文字方向。它只有两个可能的值:rtl表示文字从右到左,阿拉伯文是这种方式;ltr表示文字从左到右,包括英语和汉语在内的大多数文字采用这种方式。
(9)document.compatMode
compatMode属性返回浏览器处理文档的模式,可能的值为BackCompat(向后兼容模式)和CSS1Compat(严格模式)。
一般来说,如果网页代码的第一行设置了明确的DOCTYPE(比如<!doctype html>),document.compatMode的值都为CSS1Compat。
# 3.Document 节点的方法
# 3.1 访问元素节点
所谓 “访问” 元素节点,就是指 “得到”、“获取” 页面上的元素节点。
对节点进行操作,第一步就是要得到它。
访问元素节点主要依靠 document 对象。
# 3.2 认识 document 对象
document 对象是 DOM 中最重要的东西,几乎所有 DOM 的功能都封装在了 document 对象中。
document 对象也表示整个 HTML 文档,它是 DOM 节点树的根。
document 对象的 nodeType 属性值是 9。
typeof document; // object
document.nodeType; // 9
2
# 3.3 访问元素节点的常用方法
注意:以下方法的参数都是字符串值 ''。
| 方法 | 功能 | 兼容性 |
|---|---|---|
document.getElementById() | 通过 id 得到元素 | IE 6 |
document.getElementsByTagName() | 通过标签名得到元素数组 | IE 6 |
document.getElementsByClassName() | 通过类名得到元素数组 | IE 9 |
document.querySelector() | 通过选择器得到元素 | IE 8 部分兼容、IE 9 完全兼容 |
document.querySelectorAll() | 通过选择器得到元素数组 | IE 8 部分兼容、IE 9 完全兼容 |
Element:元素。
query:查询。
Selector:选择器。
# 3.4 getElementById()
document.getElementById() 功能是通过 id 得到元素节点。
- HTML
<div id="box">我是一个盒子</div>
<p id="para">我是一个段落</p>
2
- JS
var box = document.getElementById('box');
var para = document.getElementById('para');
2
【注意事项】
如果页面上有相同 id 的元素,则只能得到第一个。
原则上,html 中同一名称的 id 也只能出现一次。
# 3.5 延迟运行
在测试 DOM 代码时,通常 JS 代码要写到 HTML 节点的后面,否则 JS 无法找到相应的 HTML 节点。
当然,可以使用 window.onload = function(){} 事件,使页面加载完毕后,再执行指定的代码。
一般 script 标签会被放在头部或尾部。头部就是
<head></head>里面,尾部一般指<body></body>里,但也有放在</body>闭合标签之后的(最好不要这样)。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="box">我是一个盒子</div>
<p id="para">我是一个段落</p>
<script>
var box = document.getElementById('box');
var para = document.getElementById('para');
console.log(box); // <div id="box">我是一个盒子</div>
console.log(para); // <p id="para">我是一个段落</p>
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
var box = document.getElementById('box');
var para = document.getElementById('para');
console.log(box); // null
console.log(para); // null
</script>
</head>
<body>
<div id="box">我是一个盒子</div>
<p id="para">我是一个段落</p>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
window.onload = function () {
var box = document.getElementById('box');
var para = document.getElementById('para');
console.log(box); // <div id="box">我是一个盒子</div>
console.log(para); // <p id="para">我是一个段落</p>
}
</script>
</head>
<body>
<div id="box">我是一个盒子</div>
<p id="para">我是一个段落</p>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 3.6 getElementsByTagName()
getElementsByTagName() 方法的功能是通过标签名得到节点数组。
注意:得到的是一个数组!
<p>我是段落</p>
<p>我是段落</p>
<p>我是段落</p>
<p>我是段落</p>
2
3
4
var ps = document.getElementsByTagName('p');
【注意事项】
数组方便遍历,从而可以批量操控元素节点。
即使页面上只有一个指定标签名的节点,也将得到长度为 1 的数组。
任何一个节点元素也可以调用 getElementsByTagName() 方法,从而得到其内部的某种标签名的元素节点。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
window.onload = function () {
var ps = document.getElementsByTagName('p');
console.log(ps); // HTMLCollection(6) [p, p, p, p, p, p]
}
</script>
</head>
<body>
<div id="box1">
<p>我是段落</p>
<p>我是段落</p>
<p>我是段落</p>
</div>
<div id="box2">
<p>我是段落</p>
<p>我是段落</p>
<p>我是段落</p>
</div>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
window.onload = function () {
// 先得到 box1
var box1 = document.getElementById('box1');
// 得到 box1 中的 p 标签的数组
var ps_inbox1 = box1.getElementsByTagName('p');
console.log(ps_inbox1); // HTMLCollection(3) [p, p, p]
}
</script>
</head>
<body>
<div id="box1">
<p>我是段落</p>
<p>我是段落</p>
<p>我是段落</p>
</div>
<div id="box2">
<p>我是段落</p>
<p>我是段落</p>
<p>我是段落</p>
</div>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 3.7 getElementsByClassName()
getElementsByClassName() 方法的功能是通过类名得到节点数组。
- HTML
<div class="spec">我是盒子</div>
<div>我是盒子</div>
<div class="spec">我是盒子</div>
<div class="spec">我是盒子</div>
2
3
4
- JS
var spec_divs = document.getElementsByClassName('spec');
【注意事项】
getElementsByClassName() 方法从 IE9 开始兼容。
某个节点元素也可以调用 getElementsByClassName() 方法,从而得到其内部的某类名的元素节点。
# 3.8 querySelector()
querySelector() 方法的功能是通过选择器得到元素。
- HTML
<div id="box1">
<p>我是段落</p>
<p class="spec">我是段落</p>
<p>我是段落</p>
</div>
2
3
4
5
- JS
var the_p = document.querySelector('#box1 .spec');
【注意事项】
querySelector() 方法只能得到页面上一个元素,如果有多个元素符合条件,则只能得到第一个元素。
querySelector() 方法从 IE8 开始兼容,但从 IE9 开始支持 CSS3 的选择器,如:nth-child()、:[src^='dog'] 等 CSS3 选择器形式都支持良好。
注意:不能选择伪类!
# 3.9 querySelectorAll()
querySelectorAll() 方法的功能是通过选择器得到元素数组。
即使页面上只有一个符合选择器的节点,也将得到长度为 1 的数组。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<ul id="list1">
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
</ul>
<ul id="list2">
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
</ul>
<script>
var lis_inlist1 = document.querySelectorAll('#list1 li');
console.log(lis_inlist1); // NodeList(5) [li, li, li, li, li]
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 3.10 document.open(),document.close()
document.open方法清除当前文档所有内容,使得文档处于可写状态,供document.write方法写入内容。
document.close方法用来关闭document.open()打开的文档。
document.open();
document.write('hello world');
document.close();
2
3
# 3.11 document.write()
document.write方法用于向当前文档写入内容。
在网页的首次渲染阶段,只要页面没有关闭写入(即没有执行document.close()),document.write写入的内容就会追加在已有内容的后面。
// 页面显示“helloworld”
document.open();
document.write('hello');
document.write('world');
document.close();
2
3
4
5
注意,document.write会当作 HTML 代码解析,不会转义。
document.write('<p>hello world</p>');
上面代码中,document.write会将<p>当作 HTML 标签解释。