DOM系列---进阶篇

 内容提纲:html

1.DOM类型node

2.DOM扩展浏览器

3.DOM操做内容性能优化

一.DOM类型服务器

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

 

DOM类型dom

类型名函数

说明性能

Node学习

表示全部类型值的统一接口,IE不支持

Document

表示文档类型

Element

表示元素节点类型

Text

表示文本节点类型

Comment

表示文档中的注释类型

CDATASection

表示CDATA区域类型

DocumentType

表示文档声明类型

DocumentFragment

表示文档片断类型

Attr

表示属性节点类型

 

1.Node类型

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

 

Node的常量

常量名

说明

nodeType值

ELEMENT_NODE

元素

1

ATTRIBUTE_NODE

属性

2

TEXT_NODE

文本

3

CDATA_SECTION_NODE

CDATA

4

ENTITY_REFERENCE_NODE

实体参考

5

ENTITY_NODE

实体

6

PROCESSING_INSTRUCETION_NODE

处理指令

7

COMMENT_NODE

注释

8

DOCUMENT_NODE

文档根

9

DOCUMENT_TYPE_NODE

doctype

10

DOCUMENT_FRAGMENT_NODE

文档片断

11

NOTATION_NODE

符号

12

 

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

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

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

 

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

IE不支持,咱们能够模拟一个类,让IE也支持。

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

 

 

2.Document类型

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

alert(document);                                                      //document

document.nodeType;                                               //9,类型值

document.childNodes[0];                                         //DocumentType,第一个子节点对象

document.childNodes[0].nodeType;                    //非IE为10,IE为8

document.childNodes[0].nodeName;                  //IE为#comment,非IE为html

document.childNodes[1];                                       //HTMLHtmlElement

document.childNodes[1].nodeName;                       //HTML

 

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

document.documentElement;                                 //HTMLHtmlElement

 

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

document.body;                                              //HTMLBodyElement

 

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

document.doctype;                                                //DocumentType

alert(document.doctype);                                       //DocumentType,    IE会显示null

 

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

document.childNodes[0].nodeName                 //IE会是#Comment(上面已经说过了)

 

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

//属性

document.title;                                                 //获取和设置<title>标签的值

document.URL;                                                //获取URL路径

document.domain;                                            //获取域名,服务器端

document.referrer;                                            //获取上一个URL,服务器端

 

//对象集合

document.anchors;                                     //获取文档中name属性的<a>元素集合

document.links;                                         //获取文档中href属性的<a>元素集合

document.applets;                                      //获取文档中<applet>元素集合,已不用

document.forms;                                      //获取文档中<form>元素集合

document.images;                                    //获取文档中<img>元素集合

 

3.Element类型

Element类型用于表现HTML中的元素节点。在DOM基础篇中,咱们已经能够对元素节点进行查找、建立等操做,元素节点的nodeType为1,nodeName为元素的标签名(tagName)

元素节点对象在非IE浏览器能够返回它具体元素节点的对象类型。

 

元素对应类型表

元素名

类型

HTML

HTMLHtmlElement

DIV

HTMLDivElement

BODY

HTMLBodyElement

P

HTMLParamElement

 

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

 

4.Text类型

Text类型用于表现文本节点类型,文本不包含HTML,或者能够包含转义后的HTML。文本节点的nodeType为3。

问题:在同时建立两个同一级别的文本节点的时候,会产生分离的两个节点。

       var box = document.createElement('div');

       var text1 = document.createTextNode('Mr.');

   var text2 = document.createTextNode(‘Wang!’);

       box.appendChild(text1);

       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是注释的内容。

示例:<div id="box"><!--我是注释--></div>

       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属性(DOM基础篇)

因为子节点空白问题,IE和其余浏览器解释不一致。虽然能够过滤掉(详见DOM基础篇),但若是只是想获得有效子节点,可使用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(下表4 + 16)

PS:为何会出现20,那是由于知足了4和16两项,最后相加了。

 

关系掩码表

掩码

节点关系

1

无关(节点不存在)

2

居前(节点在参考点以前)

4

居后(节点在参考点以后)

8

包含(节点是参考点的祖先)

16

被包含(节点是参考点的后代)

 

为了能让全部浏览器均可以兼容,咱们必须写一个兼容性的函数。代码以下:

 1 //判断一个节点是否是另外一个节点的后代
 2 
 3 //传递参考节点(父节点),和其余节点(子节点)
 4 
 5 function contains(refNode, otherNode) {
 6 
 7     //判断支持contains,而且非Safari3.0如下浏览器
 8 
 9        if (typeof refNode.contains != 'undefined' &&
10 
11 !(BrowserDetect.browser == 'Safari' && BrowserDetect.version < 3)) {
12 
13               return refNode.contains(otherNode);
14 
15     //判断支持compareDocumentPosition的浏览器,大于16就是包含
16 
17        } else if (typeof refNode.compareDocumentPosition == 'function') {
18 
19               return !!(refNode.compareDocumentPosition(otherNode) > 16);
20 
21        } else {
22 
23       //更低版本的浏览器上述两个都不支持
24 
25       //兼容方法是经过递归一个个获取他的父节点是否存在
26 
27               var node = otherNode.parentNode;
28 
29               do {
30 
31                      if (node === refNode) {
32 
33                             return true;
34 
35                      } else {
36 
37                             node = node.parentNode;
38 
39                      }
40 
41                      } while (node != null);
42 
43               }
44 
45               return false;
46 
47 }

 

三.DOM操做内容

虽然在以前咱们已经学习了各类DOM操做的方法,这里所介绍是innerText、innerHTML、outerText和outerHTML等属性。除了以前用过的innerHTML以外,其余三个还么有涉及到(其实,其余3个并不经常使用也不建议使用!)

1.innerText属性

document.getElementById('box').innerText;        //获取文本内容(若有html直接删掉)

document.getElementById('box').innerText = 'Mr.Wang;            //设置文本(若有html转义)

 

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

document.getElementById('box').textContent;     //Firefox支持

 1  //兼容方案
 2 
 3 function getInnerText(element) {
 4 
 5        return (typeof element.textContent == 'string') ?
 6 
 7 element.textContent : element.innerText;
 8 
 9 }
10 
11  
12 
13 function setInnerText(element, text) {
14 
15        if (typeof element.textContent == 'string') {
16 
17               element.textContent = text;
18 
19        } else {
20 
21               element.innerText = text;
22 
23        }
24 
25 }

 

2.innerHTML属性(重点)

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

document.getElementById('box').innerHTML;                   //获取文本(不过滤HTML)

document.getElementById('box').innerHTML = '<b>123</b>';   //可解析HTML

 

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

box.innerHTML = "<script>alert('Wang');</script>";   //<script>元素不能被执行

 

3.outerText

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

       var box = document.getElementById('box');

       box.outerText = '<b>123</b>';

       alert(document.getElementById('box'));                     //null,建议不去使用

 

4.outerHTML

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

       var box = document.getElementById('box');

       box.outerHTML = '123';

       alert(document.getElementById('box'));                     //null,建议不去使用

 

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

for (var i = 0; i < 10; i ++) {

ul.innerHTML = '<li>item</li>';                  //避免频繁

}

//改

for (var i = 0; i < 10; i ++) {

//临时保存(建立中间临时变量,这是JS经常使用性能优化方法之一)

a = '<li>item</li>';                                   

}

ul.innerHTML = a;

 

很是感谢李老师~

相关文章
相关标签/搜索