JavaScript的DOM进阶

DOM 自身存在不少类型,在DOM 基础课程中大部分都有所接触,好比Element 类型:
表示的是元素节点,再好比Text 类型:表示的是文本节点。DOM 也提供了一些扩展功能。html


一.DOM类型
DOM 基础课程中,咱们了解了DOM 的节点而且了解怎样查询和操做节点,而自己这
些不一样的节点,又有着不一样的类型。node

1.Node 类型
Node 接口是DOM1 级就定义了,Node 接口定义了12 个数值常量以表示每一个节点的类
型值。除了IE 以外,全部浏览器均可以访问这个类型。浏览器

虽然这里介绍了12 种节点对象的属性,用的多的其实也就几个而已。服务器

  
  
           
  
  
  1. alert(Node.ELEMENT_NODE); //1,元素节点类型值 
  2. alert(Node.TEXT_NODE); //2,文本节点类型值 

咱们建议使用Node 类型的属性来代替1,2 这些阿拉伯数字,有可能你们会以为这样岂
不是很繁琐吗?而且还有一个问题就是IE 不支持Node 类型。
若是只有两个属性的话,用1,2 来代替会特别方便,但若是属性特别多的状况下,一、
二、三、四、五、六、七、八、九、十、十一、12,你根本就分不清哪一个数字表明的是哪一个节点。固然,
若是你只用1,2 两个节点,那就另当别论了。
IE 不支持,咱们能够模拟一个类,让IE 也支持。app

  
  
           
  
  
  1. if (typeof Node == 'undefined') { //IE 返回 
  2. window.Node = { 
  3. ELEMENT_NODE : 1, 
  4. TEXT_NODE : 3 
  5. }; 

2.Document 类型
Document 类型表示文档,或文档的根节点,而这个节点是隐藏的,没有具体的元素标
签。dom

  
  
           
  
  
  1. document; //document 
  2. document.nodeType; //9,类型值 
  3. document.childNodes[0]; //DocumentType,第一个子节点对象 
  4. document.childNodes[0].nodeType; //非IE 为10,IE 为8 
  5. document.childNodes[1]; //HTMLHtmlElement 
  6. document.childNodes[1].nodeName; //HTML 

若是想直接获得<html>标签的元素节点对象HTMLHtmlElement,没必要使用childNodes
属性这么麻烦,可使用documentElement 便可。ide

  
  
           
  
  
  1. document.documentElement; //HTMLHtmlElement 

在不少状况下,咱们并不须要获得<html>标签的元素节点,而须要获得更经常使用的<body>
标签,以前咱们采用的是:document.getElementsByTagName('body')[0],那么这里提供一个
更加简便的方法:document.body。函数

  
  
           
  
  
  1. document.body; //HTMLBodyElement 

在<html>以前还有一个文档声明:<!DOCTYPE>会做为某些浏览器的第一个节点来处
理,这里提供了一个简便方法来处理:document.doctype。性能

  
  
           
  
  
  1. document.doctype; //DocumentType 

PS:IE8 中,若是使用子节点访问,IE8 以前会解释为注释类型Comment 节点,而
document.doctype 则会返回null。学习

  
  
           
  
  
  1. document.childNodes[0].nodeName //IE 会是#Comment 

在Document 中有一些遗留的属性和对象合集,能够快速的帮助咱们精确的处理一些任
务。

  
  
           
  
  
  1. //属性 
  2. document.title; //获取和设置<title>标签的值 
  3. document.URL; //获取URL 路径 
  4. document.domain; //获取域名,服务器端 
  5. document.referrer; //获取上一个URL,服务器端 
  6. //对象集合 
  7. document.anchors; //获取文档中带name 属性的<a>元素集合 
  8. document.links; //获取文档中带href 属性的<a>元素集合 
  9. document.applets; //获取文档中<applet>元素集合,已不用 
  10. document.forms; //获取文档中<form>元素集合 
  11. document.p_w_picpaths; //获取文档中<img>元素集合 

3.Element 类型
Element 类型用于表现HTML 中的元素节点。在DOM 基础那章,咱们已经能够对元素
节点进行查找、建立等操做,元素节点的nodeType 为1,nodeName 为元素的标签名。
元素节点对象在非IE 浏览器能够返回它具体元素节点的对象类型。

PS:以上给出了部分对应,更多的元素对应类型,直接访问调用便可。

4.Text 类型
Text 类型用于表现文本节点类型,文本不包含HTML,或包含转义后的HTML。文本
节点的nodeType 为3。
在同时建立两个同一级别的文本节点的时候,会产生分离的两个节点。

  
  
           
  
  
  1. var box = document.createElement('div'); 
  2. var text = document.createTextNode('Mr.'); 
  3. var text2 = document.createTextNode(Lee!); 
  4. box.appendChild(text); 
  5. box.appendChild(text2); 
  6. document.body.appendChild(box); 
  7. alert(box.childNodes.length); //2,两个文本节点 

PS:把两个同邻的文本节点合并在一块儿使用normalize()便可。

  
  
           
  
  
  1. box.normalize(); //合并成一个节点 

PS:有合并就有分离,经过splitText(num)便可实现节点分离。

  
  
           
  
  
  1. box.firstChild.splitText(3); //分离一个节点 

除了上面的两种方法外,Text 还提供了一些别的DOM 操做的方法以下:

  
  
           
  
  
  1. var box = document.getElementById('box'); 
  2. box.firstChild.deleteData(0,2); //删除从0 位置的2 个字符 
  3. box.firstChild.insertData(0,'Hello.'); //从0 位置添加指定字符 
  4. box.firstChild.replaceData(0,2,'Miss'); //从0 位置替换掉2 个指定字符 
  5. box.firstChild.substringData(0,2); //从0 位置获取2 个字符,直接输出 
  6. alert(box.firstChild.nodeValue); //输出结果 

5.Comment 类型
Comment 类型表示文档中的注释。nodeType 是8,nodeName 是#comment,nodeValue
是注释的内容。

  
  
           
  
  
  1. var box = document.getElementById('box'); 
  2. alert(box.firstChild); //Comment 

PS:在IE 中,注释节点可使用!看成元素来访问。

  
  
           
  
  
  1. var comment = document.getElementsByTagName('!'); 
  2. alert(comment.length); 

6.Attr 类型
Attr 类型表示文档元素中的属性。nodeType 为11,nodeName 为属性名,nodeValue 为
属性值。DOM 基础篇已经详细介绍过,略。


二.DOM扩展
1.呈现模式
从IE6 开始开始区分标准模式和混杂模式(怪异模式),主要是看文档的声明。IE 为
document 对象添加了一个名为compatMode 属性,这个属性能够识别IE 浏览器的文档处于
什么模式若是是标准模式,则返回CSS1Compat,若是是混杂模式则返回BackCompat。

  
  
           
  
  
  1. if (document.compatMode == 'CSS1Compat') { 
  2. alert(document.documentElement.clientWidth); 
  3. else { 
  4. alert(document.body.clientWidth); 

PS:后来Firefox、Opera 和Chrome 都实现了这个属性。从IE8 后,又引入documentMode
新属性,由于IE8 有3 种呈现模式分别为标准模式8,仿真模式7,混杂模式5。因此若是
想测试IE8 的标准模式,就判断document.documentMode > 7 便可。


2.滚动
DOM 提供了一些滚动页面的方法,以下:

  
  
           
  
  
  1. document.getElementById('box').scrollIntoView(); //设置指定可见 

3.children 属性
因为子节点空白问题,IE 和其余浏览器解释不一致。虽然能够过滤掉,但若是只是想
获得有效子节点,可使用children 属性,支持的浏览器为:IE5+、Firefox3.5+、Safari2+、
Opera8+和Chrome,这个属性是非标准的。

  
  
           
  
  
  1. var box = document.getElementById('box'); 
  2. alert(box.children.length); //获得有效子节点数目 

4.contains()方法
判断一个节点是否是另外一个节点的后代,咱们可使用contains()方法。这个方法是IE
率先使用的,开发人员无须遍历便可获取此信息。

  
  
           
  
  
  1. var box = document.getElementById('box'); 
  2. alert(box.contains(box.firstChild)); //true 

PS:早期的Firefox 不支持这个方法,新版的支持了,其余浏览器也都支持,Safari2.x
浏览器支持的有问题,没法使用。因此,必须作兼容。


在Firefox 的DOM3 级实现中提供了一个替代的方法compareDocumentPosition()方法。
这个方法肯定两个节点之间的关系。

  
  
           
  
  
  1. var box = document.getElementById('box'); 
  2. alert(box.compareDocumentPosition(box.firstChild)); //20 

PS:为何会出现20,那是由于知足了4 和16 两项,最后相加了。为了能让全部浏览
器均可以兼容,咱们必须写一个兼容性的函数。

  
  
           
  
  
  1. //传递参考节点(父节点),和其余节点(子节点) 
  2. function contains(refNode, otherNode) { 
  3. //判断支持contains,而且非Safari 浏览器 
  4. if (typeof refNode.contains != 'undefined' && 
  5. !(BrowserDetect.browser == 'Safari' && BrowserDetect.version < 3)) { 
  6. return refNode.contains(otherNode); 
  7. //判断支持compareDocumentPosition 的浏览器,大于16 就是包含 
  8. else if (typeof refNode.compareDocumentPosition == 'function') { 
  9. return !!(refNode.compareDocumentPosition(otherNode) > 16); 
  10. else { 
  11. //更低的浏览器兼容,经过递归一个个获取他的父节点是否存在 
  12. var node = otherNode.parentNode; 
  13. do { 
  14. if (node === refNode) { 
  15. return true
  16. else { 
  17. node = node.parentNode; 
  18. while (node != null); 
  19. return false

三.DOM操做内容
虽然在以前咱们已经学习了各类DOM 操做的方法,这里所介绍是innerText、
innerHTML、outerText 和outerHTML 等属性。除了以前用过的innerHTML 以外,其余三个
还么有涉及到。


1.innerText 属性

  
  
           
  
  
  1. document.getElementById('box').innerText; //获取文本内容(若有html 直接过滤掉) 
  2. document.getElementById('box').innerText = 'Mr.Lee'//设置文本(若有html 转义) 

PS:除了Firefox 以外,其余浏览器均支持这个方法。但Firefox 的DOM3 级提供了另
外一个相似的属性:textContent,作上兼容便可通用。

  
  
           
  
  
  1. document.getElementById('box').textContent; //Firefox 支持 
  2. //兼容方案 
  3. function getInnerText(element) { 
  4. return (typeof element.textContent == 'string') ? 
  5. element.textContent : element.innerText; 
  6. function setInnerText(element, text) { 
  7. if (typeof element.textContent == 'string') { 
  8. element.textContent = text; 
  9. else { 
  10. element.innerText = text; 

2.innerHTML 属性
这个属性以前就已经研究过,不拒绝HTML。

  
  
           
  
  
  1. document.getElementById('box').innerHTML; //获取文本(不过滤HTML) 
  2. document.getElementById('box').innerHTML = '<b>123</b>'//可解析HTML 

虽然innerHTML 能够插入HTML,但自己仍是有必定的限制,也就是所谓的做用域元
素,离开这个做用域就无效了。

  
  
           
  
  
  1. box.innerHTML = "<script>alert('Lee');</script>"//<script>元素不能被执行 
  2. box.innerHTML = "<style>red;< /style>"//<style>元素不能被执行 

3.outerText
outerText 在取值的时候和innerText 同样,同时火狐不支持,而赋值方法至关危险,他
不单替换了文本内容,还将元素直接抹去。

  
  
           
  
  
  1. var box = document.getElementById('box'); 
  2. box.outerText = '<b>123</b>'
  3. alert(document.getElementById('box')); //null,建议不去使用 

4.outerHTML
outerHTML 属性在取值和innerHTML 一致,但和outerText 也同样,很危险,赋值的之
后会将元素抹去。

  
  
           
  
  
  1. var box = document.getElementById('box'); 
  2. box.outerHTML = '123'
  3. alert(document.getElementById('box')); //null,建议不去使用,火狐旧版未抹去 

PS:关于最经常使用的innerHTML 属性和节点操做方法的比较,在插入大量HTML 标记时
使用innerHTML 的效率明显要高不少。由于在设置innerHTML 时,会建立一个HTML 解
析器。这个解析器是浏览器级别的(C++编写),所以执行JavaScript 会快的多。但,建立和
销毁HTML 解析器也会带来性能损失。最好控制在最合理的范围内,以下:

  
  
           
  
  
  1. for (var i = 0; i < 10; i ++) { 
  2. ul.innerHTML = '<li>item</li>'//避免频繁 
  3. //改 
  4. for (var i = 0; i < 10; i ++) { 
  5. a = '<li>item</li>'//临时保存 
  6. ul.innerHTML = a; 
相关文章
相关标签/搜索