DOM系列---進階篇【轉】


 

 內容提綱:

1.DOM類型

2.DOM擴展

3.DOM操作內容

一.DOM類型

DOM基礎篇中,我們了解了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來代替會特別方便,但如果屬性特別多的情況下,1、2、3、4、5、6、7、8、9、10、11、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;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM