JavaScript高級-unit10 DOM

簡介

DOM描述了一個層次化的節點樹,容許開發人員添加、移除和修改頁面。javascript

節點

根據 W3C 的 HTML DOM 標準,HTML 文檔中的全部內容都是節點:html

  • 整個文檔是一個文檔節點
  • 每一個 HTML 元素是元素節點
  • HTML 元素內的文本是文本節點
  • 每一個 HTML 屬性是屬性節點
  • 註釋是註釋節點

每一個節點都有一個nodeType屬性,用於代表節點的類型。並非全部節點類型都受到Web瀏覽器支持,最經常使用的事元素和文本節點。java

Node.ELEMENT_NODE(1); // 元素
Node.ATTRIBUTE_NODE(2); // 屬性
Node.TEXT_NODE(3); // 文本
Node.CDATA_SECTION_NODE(4);
Node.ENTITY_REFERENCE_NODE(5);
Node.ENTITY_NODE(6);
Node.PROCESSING_INSTRUCTION_NODE(7);
Node.COMMENT_NODE(8); // 註釋
Node.DOCUMENT_NODE(9); // 文檔
Node.DOCUMENT_TYPE_NODE(10);
Node.DOCUMENT_FRAGMENT_NODE(11);
Node.NOTATION_NODE(12);node

由於IE沒有公開Node類型的構造函數,因此肯定節點類型以下:跨域

// nodeType 是隻讀的
if (someNode.nodeType == 1) {
    alert("Node is an element");
}

Node類型

一、nodeName 和 nodeValue 屬性數組

// 使用前先檢查節點類型,確認是不是一個元素,對於元素節點
// nodeName 保存的是標籤名(節點的名稱),nodeValue = null (節點的值);
if (someNode.nodeType == 1) {
    value = someNode.nodeName;    // nodeName的值是元素的標籤名
}

二、 節點關係瀏覽器

每一個節點都有一個 childNodes 屬性,保存着一個 NodeList 對象。安全

  1. 是一個數組對象,保存一組有序的節點,能夠經過位置訪問節點。有length屬性,但不是數組實例。
  2. 基於DOM結構動態執行查詢結果,結構的變化可以自動反應着NodeList對象中。
  3. 能夠用 item() 方法訪問其中的節點。
var firstChild  = someNode.childNodes[0];
var secondChild = someNode.childNodes.item(1); 

// 將NodeList對象轉化爲數組
function convertToArray(nodes) {
    var array = null;
    try {
        array = Array.prototype.slice.call(node,0);    // 針對非 IE 瀏覽器
    } catch {
        array = new Array();
        for (var i=0, len=nodes.length; I < len; i++) {
            array.push(nodes[I]);
        }
    }
    return array;
}
  • parentNode 屬性:指向文檔樹中的父節點
  • 父節點的 firstChild 和 lastChild 屬性指向第一個和最後一個
  • previousSibling: 上一個同胞節點
  • nextSibling: 下一個同胞節點
  • hasChildNodes(): 節點包含一個或多個子節點返回 true
  • ownerDocument: 指向表示整個文檔的文檔節點
  • document.documentElement - 所有文檔
  • document.body - 文檔的主體

三、操做節點app

如下方法都須要取得父節點(使用 parentNode 屬性)dom

  • appendChild(): 向 childNodes 列表末尾添加一個節點。若是已存在,從原來位置移動到新位置
  • insertBefore(): 插入節點,接受兩個參數,要出入的節點和參考節點(誰的前面)
  • replaceChild(): 替換節點,接受兩個參數,要插入的節點和要替換的節點
  • removeChild(): 移除節點

如下兩個方法是全部類型的節點都有

  • cloneNode(): 建立節點的副本,參數爲true,複製節點及整個子節點樹,false只複製節點自己,沒有父節點,須要用上面方法添加到文檔中
  • normalize(): 處理文檔樹中的文本節點。可能會出現文本節點不包含文本,或者接連出現兩個文本節點。調用這方法,若是找到空文本,則刪除;找到相鄰文本節點,則合併爲一個

Document 類型

JavaScript經過 Document 類型表示文檔。在瀏覽器中,document 對象是 HTMLDocument(繼承自 Document 類型)的一個實例,表示整個HTML頁面。並且 document 也是 window 對象的一個屬性,所以能夠將其做爲全局對象來訪問。經過這個文檔對象,不只能夠取得與頁面有關的信息,並且還能操做頁面的外觀及其底層結構。

  • nodeName 的值爲 「#document」;
  • nodeValue 的值爲 null;
  • parentNode 的值爲 null;
  • ownerDocument 的值爲 null;
  • 其子節點多是一個 DocumentType(最多一個)、Element(最多一個)、ProcessingInstruction 或 Comment。

一、文檔的子節點

內置的訪問子節點的快捷方式:

  • documentElement 屬性:始終指向HTML頁面的<html>元素
  • childNodes 列表訪問文檔元素

做爲內置的HTMLDocument對象,document 對象有一個 body 屬性,直接指向 <body> 元素。

// 全部瀏覽器都支持
var html = document.documentElement;    // 取得對<html>對引用
var body = document.body;    // 取得對<body>對引用

用不着在 document 對象上調用 appendChild()、removeChild()和replaceChild()方法,由於文檔類型(若是存在)是隻讀的,並且它只能有一個元素子節點(一般早存在)。

二、文檔信息

document 對象還有一些標準的Document對象所沒有的屬性。這些對象表現的網頁的一些信息。

// 取的文檔標題
var originalTitle = document.title;
// 設置文檔標題
document.title = "New page title";

// 取得完成的URL
var url = document.URL;
// 取的域名
var domain = document.domain;
// 取的來源頁面的URL
var referrer = document.referrer;
  • 只有 domain 能夠設置,若是包含子域名,不能設置爲URL中不包含的域。
  • 因爲跨域安全限制,來自不一樣子域的頁面沒法經過 Javascript 通訊,能夠將每一個頁面的document.domain設置爲相同值,就能夠互相訪問對方包含的JavaScript對象了。
  • 若是域名一開始是「鬆散的」,就不能設爲「緊繃的」,設爲「wrox.com」,就不能設爲「p2p.wrox.com」。

三、查找元素

取得特定的某個或某組元素的引用,而後執行一些操做。

  • getElementById(): 要獲取的元素 id,返回第一個出現的,若是沒找到返回 null
  • getElementsByTagName(): 參數(要取得元素的標籤名),返回包含零個或多個元素的 NodeList。在HTML文檔中,返回一個 HTMLCollection 對象,做爲動態集合。傳入「*」,取得文檔中的全部元素
  • getElementsByName(): 返回給定 name 特性的全部元素。最經常使用取得單選按鈕(單選按鈕必須具備相同的 name 特性)
// 取得頁面中全部的<img>元素,並返回一個HTMLCollection
var images = document.getElementsByTagName("img");
alert(images.length);    // 圖像的數量
alert(images[0].src);    // 第一個圖像元素的src特性
alert(images.item(0).src);    // 第一個圖像元素的src特性

HMTLCollection 對象

  • 有一個 namedItem() 方法,能夠經過元素的 name 特性取得集合中的項
  • 支持按名稱訪問項
<img src="my image.gif" name="myImage">
var myImage = images.namedItem("myImage");

var myImage = images["myImage"];

四、特殊集合

除了屬性和方法,document 對象還有一些特殊的集合,都是 HTMLCollection對象,

  • document.anchors ,包含文檔中全部帶 name 特性的 <a> 元素;
  • document.applets ,全部的 <applet>元素,不建議使用;
  • document.forms ,文檔中全部的 <form> 元素;
  • document.images ,文檔中全部的 <img> 元素;
  • document.links ,文檔中全部帶 href 特性的 <a> 元素。

五、DOM一致性檢測

document.implementation 屬性提供相應信息和功能的對象,與瀏覽器對 DOM 的實現直接對應。
規定一個方法:hasFeature(),接受兩個參數:要檢測的 DOM 功能名稱及版本號

var hasXmlDom = document.implementation.hasFeature("XML","1.0");

六、文檔寫入

  • write(): 原樣寫入
  • writeln(): 在字符串的末尾添加一個換行符(n)
  • open(): 打開網頁的輸出流
  • close(): 關閉網頁的輸出流
// 用 write() 和 written() 動態地包含外部資源
<html>
<head>
    <title>document.write() Example</title>
</head>
<body>
    <script type="text/javascript">
        document.write("<script type=\"text/javascript\" src=\"file.js\">" +
            "<\/script>");
    </script>
</body>

嚴格型 XHTML 文檔不支持文檔寫入。

Element 類型

Element 類型用於表現 XML 或 HTML 元素,提供了對元素標籤名、字節點及特性的訪問。

  • nodeType 的值爲 1;
  • nodeName 的值爲元素的標籤名;
  • nodeValue 的值爲 null;
  • parentNode 多是 Document 或 Element;
  • 其子節點多是 Element、Text、Comment、ProcessingInstruction、CDATASection 或 EntityReference;
  • 訪問元素標籤名,能夠是使用 nodeName 屬性或者 tagName 屬性。
<div id="myDiv"></div>
var div = document.getElementById("myDiv");
alert(div.tagName);    // "DIV"
alert(div.tagName == div.nodeName);    // true

在 HTML 中,標籤名始終都以所有大寫表示;而在 XML(有時包括 XHTML),標籤名始終與源代碼中的保持一致。

if (element.tagName.toLowerCase() == "div") {    // 適用於任何文檔
    // ...
}

一、HTML 元素

全部的 HTML 元素都由 HTMLElement 類型表示。每一個 HTML 元素都存在的下列標準特性。

  • id,元素中文檔中的惟一標識符
  • title,有關元素的附加說明信息,通常經過工具提示條現實出來
  • lang,元素內容的語言代碼
  • dir,語言的方向,值爲「ltr」(左到右),或「rtl」(右到左)
  • className,與元素的 class 特性對應,即爲元素指定的CSS類。(是 ECMAScript 的保留字)
// 上述這些屬性均可以用來取得或修改相應的特性值
<div id="myDiv" class="bd" title="Body text" lang="en" dir="ltr"></div>
var div = document.getElementById("myDiv");
alert(div.id);
div.id = "someOtherId";
alert(div.className);
div.className = "ft";

二、取得特性

每一個元素都有一或多個特性,這些特性的用途是給出相應元素或其內容的附加信息。

  • getAttribute(): 取得特性,傳遞的特性名與實際的特性名相同,能夠是自定義的特性。
  • setAttribute(): 設置特性。設置的特性名統一轉爲小寫。
  • removeAttribute(): 不只會清除特性值,也會從元素中完成刪除特性。

有兩類特殊的特性:

  • style: 經過getAttribute()訪問返回特性值中包含的文本,經過屬性來訪問返回一個對象。
  • onclick: 經過 getAttribute()返回相應代碼的字符串,訪問屬性時返回函數。
div.setAttribute("id","someOtherId");

三、attributes 屬性

attributes 屬性包含一系列節點,每一個節點的 nodeName 就是特性的名稱,而節點的 nodeValue 就是特性的值。
包含一個 NamedNodeMap,「動態」集合。

  • getNamedItem():返回 nodeName 等於 name 的節點
  • removeNamedItem():從列表中移除 nodeName 屬性等於 name 的節點
  • setNamedItem():向類表添加節點,以節點的 nodeName 屬性爲索引
  • item(pos):返回位於數字pos 的節點
var id = element.attributes.getNamedItem("id").nodeValue;
var id = element.attributes["id"].nodeValue;

遍歷元素的特性,attributes 屬性能夠派上用場。

function outputAttributes(element) {
    var pairs = new Array(),
        attrName,
        attrValue,
        y,
        len;
     
     for(y = 0, len = element.attributes.length; y < len; y++) {
         attrName = element.attributes[y].nodeName;
         attrValue = element.attributes[y].nodeValue;
         if (element.attributes[y].specified) {
             pairs.push(attrName + "=\"" + attrValue + "\"");
         }
     }
     return pairs.join(" ");
}

// attributes 對象的中的特性,不一樣瀏覽器返回的順序不一樣
// IE7 及更早版本會返回 HTML 元素中全部可能的特性,包括沒有指定的特性。每一個特性節點都有一個 specified 的屬性,true:在 HTML 中指定來相應特性,要麼能夠經過 setAttribute() 方法設置了該特性。

四、建立元素

// 接受一個參數,即要建立元素的標籤名
var div = document.createElement("div");

// 也爲新元素設置了 ownerDocument 屬性,還能夠操做元素的特性,添加更多的子節點
div.id = "myNewDiv";
div.className = "box";

// 新元素添加到文檔樹中 appendChild()、insertBefore()、replaceChild()
document.body.appendChild(div);

在 IE 中能夠另外一種方法,傳入完整的元素標籤

var div = document.createElement("<div id=\"myNewDiv\" class=\"box\"></div>");

五、元素的子節點

不一樣瀏覽器看待節點是不一樣的。
若是要經過 childNodes 屬性遍歷子節點,不要忘了瀏覽器之間的區別,一般先檢查一下 nodeType 屬性

for (var y = 0, len = element.childNodes.length; y < len; y++) {
    // 表示是元素節點
    if (element.childNodes[y].nodeType == 1) {
        // ...
    }
}

經過特定的標籤名取得子節點或後代節點

var ul = document.getElementById("myList");
var items = ul.getElementsByTagName("li");

Text 類型

文本節點由 Text 類型表示,包含純文本內容,即包含轉義後的 HTML 字符,但不包含 HTML 代碼。

  • nodeType 的值爲 3;
  • nodeName 的值爲 「#text」;
  • nodeValue 的值爲節點所包含的文本;
  • parentNode 是一個 Element;
  • 不支持(沒有)子節點;

經過 nodeValue 屬性或 data 屬性訪問 Text 節點包含的文本。

  • appendData(text):將 text 添加到節點的末尾。
  • deleteData(offset, count):從 offset 指定的位置開始刪除 count 個子符。
  • insertData(offset, text):在 offset 指定的位置插入 text。
  • replaceData(offset, count, text):用 text 替換從 offset 指定的位置開始到 offset + count 爲止的文本。
  • splitText(offset):從 offset 指定的位置將當前文本節點分爲兩個文本節點。
  • substringData(offset, count):提取從 offset 指定的位置開始到 offset + count 爲止的字符串。

在默認狀況下,每一個能夠包含內容的元素最多隻能有一個文本節點,並且必須確實有內容存在。

// 沒有內容,也就沒有文本節點
<div></div>

// 有空格,於是有一個文本節點
<div> </div>

// 有內容,於是有一個文本節點
<div>hello world!</div>

// 訪問,先取得引用
var textNode = div.firstChild;  // 獲取 div.childNodes[0]
textNode.nodeValue = "some other message";

在修改文本節點時,此時的字符串會經 HTML 編碼(轉義)。

一、建立文本節點

  • document.createTextNode():建立文本節點,接受一個參數,要插入的文本,也會進行轉義。
var element = document.createElement("div");
element.className = "message";

var textNode = document.createTextNode("Hello world");
element.appendChild(textNode);

var anotherTextNode = document.createTextNode("Yippee");
element.appendChild(anotherTextNode);

document.body.appendChild(element);

若是兩個文本節點是相鄰的同胞節點,那麼這兩個節點中的文本會連起來顯示,中間不會有空格。

二、規範化文本節點

  • normalize():在一個包含兩個或多個文本節點的父元素上調用,則會將全部文本節點合併成一個節點。

Comment 類型

  • nodeType 的值爲 8;
  • nodeName 的值爲 「#comment」;
  • nodeValue 的值是註釋的內容;
  • parentNode 多是 Document 或 Element;
  • 不支持(沒有)子節點。

和 Text 類型類似,能夠經過 nodeValue 或 data 屬性來取得註釋的內容。

<div id="myDiv"><!-- A comment --></div>

// 經過父節點訪問
var div = document.getElementById("myDiv"); 
var comment = div.firstChild;
alert(comment.data);

使用 document.createComment() 爲其傳遞註釋文本也能夠建立註釋節點。

var comment = document.createComment("A comment");

若是要訪問註釋節點,必定要保證他們是 <html> 元素的後代。

DocumentFragment 類型(文檔片斷)

  • 在文檔中沒有對應的標記;
  • nodeType 的值爲 11;
  • nodeName 的值爲 「#document-fragment」;
  • nodeValue 的值爲 null;
  • parentNode 的值爲 null;

不能把文檔片斷直接添加到文檔中,但能夠做爲一個「倉庫」,保存未來可能添加到文檔中的節點。若是將文檔中的節點添加到文檔片斷中,就會從文檔樹移除該節點,文檔片斷自己不會成爲文檔樹的一部分。

// 建立文檔片斷 
var fragment = document.createDocumentFragment();

// 爲 ul 元素添加3個列表項
var ul = document.getElementById("myList");
var li = null;

for (var i=0; i < 3; i++) {
    li = document.createElement("li");
    li.appendChild(document.createTextNode("Item " + (i+1)));
    fragment.appendChild(li);
}

ul.appendChild(fragment);

Attr 類型

元素的特性在 DOM 中以 Attr 類型來表示。特性就是存在於元素的 attributes 屬性中的節點。

  • nodeType 的值 2;
  • nodeName 的值是特性的名稱;
  • nodeValue 的值是特性的值;
  • parentNode 的值爲 null;
  • 在 HTML 中不支持子節點;
  • 在 XML 中子節點能夠是 Text 或 EntityReference。

儘管是節點,但不是 DOM 文檔樹但一部分。有3個屬性:

  • name:特性名稱(與 nodeName 相同);
  • value:特性的值(與 nodeValue 的值相同);
  • specified:一個布爾值,區別特性在代碼中是指定的,仍是默認的。
// 建立
var attr = document.createAttribute("align");
attr.value = "left";
// 添加到元素中
element.setAttributeNode(attr);
相關文章
相關標籤/搜索