DOM 自身存在很多类型,在DOM 基础课程中大部分都有所接触,比如Element 类型:
表示的是元素节点,再比如Text 类型:表示的是文本节点。DOM 也提供了一些扩展功能。
一.DOM类型
DOM 基础课程中,我们了解了DOM 的节点并且了解怎样查询和操作节点,而本身这
些不同的节点,又有着不同的类型。
1.Node 类型
Node 接口是DOM1 级就定义了,Node 接口定义了12 个数值常量以表示每个节点的类
型值。除了IE 之外,所有浏览器都可以访问这个类型。
虽然这里介绍了12 种节点对象的属性,用的多的其实也就几个而已。
- alert(Node.ELEMENT_NODE); //1,元素节点类型值
- alert(Node.TEXT_NODE); //2,文本节点类型值
我们建议使用Node 类型的属性来代替1,2 这些阿拉伯数字,有可能大家会觉得这样岂
不是很繁琐吗?并且还有一个问题就是IE 不支持Node 类型。
如果只有两个属性的话,用1,2 来代替会特别方便,但如果属性特别多的情况下,1、
2、3、4、5、6、7、8、9、10、11、12,你根本就分不清哪个数字代表的是哪个节点。当然,
如果你只用1,2 两个节点,那就另当别论了。
IE 不支持,我们可以模拟一个类,让IE 也支持。
- if (typeof Node == 'undefined') { //IE 返回
- window.Node = {
- ELEMENT_NODE : 1,
- TEXT_NODE : 3
- };
- }
2.Document 类型
Document 类型表示文档,或文档的根节点,而这个节点是隐藏的,没有具体的元素标
签。
- document; //document
- document.nodeType; //9,类型值
- document.childNodes[0]; //DocumentType,第一个子节点对象
- document.childNodes[0].nodeType; //非IE 为10,IE 为8
- document.childNodes[1]; //HTMLHtmlElement
- document.childNodes[1].nodeName; //HTML
如果想直接得到标签的元素节点对象HTMLHtmlElement,不必使用childNodes
属性这么麻烦,可以使用documentElement 即可。
- document.documentElement; //HTMLHtmlElement
在很多情况下,我们并不需要得到标签的元素节点,而需要得到更常用的
标签,之前我们采用的是:document.getElementsByTagName('body')[0],那么这里提供一个
更加简便的方法:document.body。
- document.body; //HTMLBodyElement
在之前还有一个文档声明:会作为某些浏览器的第一个节点来处
理,这里提供了一个简便方法来处理:document.doctype。
- document.doctype; //DocumentType
PS:IE8 中,如果使用子节点访问,IE8 之前会解释为注释类型Comment 节点,而
document.doctype 则会返回null。
- document.childNodes[0].nodeName //IE 会是#Comment
在Document 中有一些遗留的属性和对象合集,可以快速的帮助我们精确的处理一些任
务。
3.Element 类型
Element 类型用于表现HTML 中的元素节点。在DOM 基础那章,我们已经可以对元素
节点进行查找、创建等操作,元素节点的nodeType 为1,nodeName 为元素的标签名。
元素节点对象在非IE 浏览器可以返回它具体元素节点的对象类型。
PS:以上给出了部分对应,更多的元素对应类型,直接访问调用即可。
4.Text 类型
Text 类型用于表现文本节点类型,文本不包含HTML,或包含转义后的HTML。文本
节点的nodeType 为3。
在同时创建两个同一级别的文本节点的时候,会产生分离的两个节点。
- var box = document.createElement('div');
- var text = document.createTextNode('Mr.');
- var text2 = document.createTextNode(Lee!);
- box.appendChild(text);
- box.appendChild(text2);
- document.body.appendChild(box);
- alert(box.childNodes.length); //2,两个文本节点
PS:把两个同邻的文本节点合并在一起使用normalize()即可。
- box.normalize(); //合并成一个节点
PS:有合并就有分离,通过splitText(num)即可实现节点分离。
- box.firstChild.splitText(3); //分离一个节点
除了上面的两种方法外,Text 还提供了一些别的DOM 操作的方法如下:
- var box = document.getElementById('box');
- box.firstChild.deleteData(0,2); //删除从0 位置的2 个字符
- box.firstChild.insertData(0,'Hello.'); //从0 位置添加指定字符
- box.firstChild.replaceData(0,2,'Miss'); //从0 位置替换掉2 个指定字符
- box.firstChild.substringData(0,2); //从0 位置获取2 个字符,直接输出
- alert(box.firstChild.nodeValue); //输出结果
5.Comment 类型
Comment 类型表示文档中的注释。nodeType 是8,nodeName 是#comment,nodeValue
是注释的内容。
- var box = document.getElementById('box');
- alert(box.firstChild); //Comment
PS:在IE 中,注释节点可以使用!当作元素来访问。
- var comment = document.getElementsByTagName('!');
- alert(comment.length);
6.Attr 类型
Attr 类型表示文档元素中的属性。nodeType 为11,nodeName 为属性名,nodeValue 为
属性值。DOM 基础篇已经详细介绍过,略。
二.DOM扩展
1.呈现模式
从IE6 开始开始区分标准模式和混杂模式(怪异模式),主要是看文档的声明。IE 为
document 对象添加了一个名为compatMode 属性,这个属性可以识别IE 浏览器的文档处于
什么模式如果是标准模式,则返回CSS1Compat,如果是混杂模式则返回BackCompat。
- if (document.compatMode == 'CSS1Compat') {
- alert(document.documentElement.clientWidth);
- } else {
- alert(document.body.clientWidth);
- }
PS:后来Firefox、Opera 和Chrome 都实现了这个属性。从IE8 后,又引入documentMode
新属性,因为IE8 有3 种呈现模式分别为标准模式8,仿真模式7,混杂模式5。所以如果
想测试IE8 的标准模式,就判断document.documentMode > 7 即可。
2.滚动
DOM 提供了一些滚动页面的方法,如下:
- document.getElementById('box').scrollIntoView(); //设置指定可见
3.children 属性
由于子节点空白问题,IE 和其他浏览器解释不一致。虽然可以过滤掉,但如果只是想
得到有效子节点,可以使用children 属性,支持的浏览器为:IE5+、Firefox3.5+、Safari2+、
Opera8+和Chrome,这个属性是非标准的。
- var box = document.getElementById('box');
- alert(box.children.length); //得到有效子节点数目
4.contains()方法
判断一个节点是不是另一个节点的后代,我们可以使用contains()方法。这个方法是IE
率先使用的,开发人员无须遍历即可获取此信息。
- var box = document.getElementById('box');
- alert(box.contains(box.firstChild)); //true
PS:早期的Firefox 不支持这个方法,新版的支持了,其他浏览器也都支持,Safari2.x
浏览器支持的有问题,无法使用。所以,必须做兼容。
在Firefox 的DOM3 级实现中提供了一个替代的方法compareDocumentPosition()方法。
这个方法确定两个节点之间的关系。
- var box = document.getElementById('box');
- alert(box.compareDocumentPosition(box.firstChild)); //20
PS:为什么会出现20,那是因为满足了4 和16 两项,最后相加了。为了能让所有浏览
器都可以兼容,我们必须写一个兼容性的函数。
- //传递参考节点(父节点),和其他节点(子节点)
- function contains(refNode, otherNode) {
- //判断支持contains,并且非Safari 浏览器
- if (typeof refNode.contains != 'undefined' &&
- !(BrowserDetect.browser == 'Safari' && BrowserDetect.version < 3)) {
- return refNode.contains(otherNode);
- //判断支持compareDocumentPosition 的浏览器,大于16 就是包含
- } else if (typeof refNode.compareDocumentPosition == 'function') {
- return !!(refNode.compareDocumentPosition(otherNode) > 16);
- } else {
- //更低的浏览器兼容,通过递归一个个获取他的父节点是否存在
- var node = otherNode.parentNode;
- do {
- if (node === refNode) {
- return true;
- } else {
- node = node.parentNode;
- }
- } while (node != null);
- }
- return false;
- }
三.DOM操作内容
虽然在之前我们已经学习了各种DOM 操作的方法,这里所介绍是innerText、
innerHTML、outerText 和outerHTML 等属性。除了之前用过的innerHTML 之外,其他三个
还么有涉及到。
1.innerText 属性
- document.getElementById('box').innerText; //获取文本内容(如有html 直接过滤掉)
- document.getElementById('box').innerText = 'Mr.Lee'; //设置文本(如有html 转义)
PS:除了Firefox 之外,其他浏览器均支持这个方法。但Firefox 的DOM3 级提供了另
外一个类似的属性:textContent,做上兼容即可通用。
- document.getElementById('box').textContent; //Firefox 支持
- //兼容方案
- function getInnerText(element) {
- return (typeof element.textContent == 'string') ?
- element.textContent : element.innerText;
- }
- function setInnerText(element, text) {
- if (typeof element.textContent == 'string') {
- element.textContent = text;
- } else {
- element.innerText = text;
- }
- }
2.innerHTML 属性
这个属性之前就已经研究过,不拒绝HTML。
- document.getElementById('box').innerHTML; //获取文本(不过滤HTML)
- document.getElementById('box').innerHTML = '123'; //可解析HTML
虽然innerHTML 可以插入HTML,但本身还是有一定的限制,也就是所谓的作用域元
素,离开这个作用域就无效了。
- box.innerHTML = ""; //