小白讀《JavaScript高階程式設計》DOM基礎部分
DOM
DOM(文件物件模型)是針對HTML和XML文件 的一個API(應用程式程式設計介面)。
節點層次
DOM可以將任何HTML或XML文件描繪成一個由多層節點構成的結構。
每個文件只能有一個文件元素,在HTML頁面中,文件元素始終都是<html>
元素。
總共有12種節點型別:
Node型別
DOM1級定義了一個Node介面,該介面將由DOM中的所有節點型別實現。
JavaScript中的所有節點型別都繼承自Node型別。
nodeType屬性:用於表明節點的型別。
12個數值 常量來表示節點型別,任何節點型別必居其一。
- 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)。
nodeName和nodeValue屬性
瞭解節點的具體資訊。
節點關係
每個節點都有一個childNodes屬性,其中儲存著一個NodeList物件。
NodeList物件:一種類陣列的物件(不是陣列,但是有length)。
通用的將NodeList物件轉為陣列的方法:
function converToArray(nodes) { var array = null; try { array = Array.prototype.slice.call(nodes,0); //針對非IE瀏覽器 } catch (ex) { array = new Array(); for (var i = 0,len = nodes.length; i < len; i++) { array.push(nodes[i]); } } return array; }
每個節點都有一個parentNode屬性,該屬性指向文件樹中的父節點。
對於同胞節點,通過使用列表中每個節點的previousSibling(上一個節點)和nextSibling(下一個節點)屬性,可以訪問同一列表中的其他節點。
父節點的firstChild和lastChild屬性分別指向其childNodes列表中的第一個和最後一個節點。
hasChildNodes()方法:返回是否有位元組點,Boolean型別。
每個節點都有的屬性:ownerDocument:該屬性指向表示整個文件的文件節點。
操作節點
appendChild()方法:用於向childNodes列表的末尾新增一個節點。
appendChild()返回新增的節點。
如果appendChild()中的節點已經是文件的一部分了,就將該節點從原來位置轉移到新位置。
insertBefore()方法:接受兩個引數:要插入的節點和作為參照的節點。
插入節點後,被插入的節點會變成參照節點的前一個同胞節點(previousSibling),同時被方法返回。
如果參照節點為null,則同appendChild()方法。
replaceChild()方法:接受兩個引數:要插入的節點和要替換的節點。
removeChild()方法:接受一個引數,即是要移除的節點。
其他方法
兩個所有型別的節點都有的方法:
cloneNode():用於建立呼叫這個方法的節點的一個完全相同的副本。
接受一個布林值引數,表示是否執行深複製。
true:深複製,複製節點及其整個子節點樹。
false:淺複製,只複製節點本身。
normalize():這個方法唯一的作用就是處理文件樹中的文字節點。
刪除文字,合併相鄰文字節點。
Document型別
Document節點具有下列特徵:
- nodeType的值為9;
- nodeName的值為"#document";
- nodeValue的值為null;
- parentNode的值為null;
- ownerDocument的值為null;
- 其子節點可能是一個DocumentType(最多一個)、Element(最多一個)、ProcessingInstruction或Comment。
文件的子節點
documentElement屬效能更快捷、更直接地訪問HTML中的<html>
元素。
獲取body元素:document.body
獲取<!DOCTYPE>
標籤:document.doctype
文件資訊
類似的還有:
document.title;
document.URL;(http獲得的頁面的URL)
document.domain(域名)
查詢元素
兩個方法:
- getElementById():通過id屬性(怪癖:name屬性也會被呼叫)
- getElementsByTagName():通過標籤名。
HTMLDocument型別獨有的方法:
getElementsByName():通過name屬性。
特殊集合
都是HTMLCollection物件:
- document.anchors:所有帶name特性發
<a>
元素。 - document.applets:文件中所有的
<applet>
元素。 - document.forms
- document.images
- document.links:文件中所有帶href特性的
<a>
元素。
DOM一致性檢測
document.implementation規定了一個方法:hasFeature()。
var hasXmlDom = document.implementation。hasFeature("XML","1.0");
文件寫入
4個方法:
- write():接受一個字串
- writeln():接受一個字串
- open():開啟網頁的輸出流
- close():關閉網頁的輸出流
Element型別
- nodeType的值為1
- nodeName的值為元素的標籤名
- nodeValue的值為null
- parentNode可能是Document或Element;
- 其子節點可能是Element、Text、Comment、ProcessingInstruction、CDATASection或EntityReference。
在HTML中,標籤名始終都以大寫表示,而在XML(有時候也包括XHTML)中,標籤名則始終會與原始碼中的保持一致。
element.tagName.toLowerCase() == "div"
HTML元素
所有HTML元素都由HTMLElement型別表示。
- id,元素在文件中的唯一識別符號。
- title,有關元素的附加說明資訊,一般通過工具提示條顯示出來。
- lang,元素內容的語言程式碼,很少使用。
- dir,語言的方向,ltr、rtl。
- className,與元素的class特性對應。
取得特性
每個元素都有一個或多個特性,這些特性的用途是給出相應元素或其內容的附加資訊。
操作特性的DOM方法主要有三個:
- getAttribute():引數是特性名的字串。
- setAttribute():同上
- removeAttribute():同上
兩類特殊的特性:style和onclick。
設定特性
setAttribute(),替換或者建立。
這個方法設定的特性名會統一轉換為小寫形式。
attributes屬性
Element型別是使用attributes屬性的唯一一個DOM節點型別。
attributes屬性中包含一個NameNodeMap。
NameNodeMap物件擁有的方法:
- getNameItem(name):返回nodeName屬性等於name的節點。
- removeNamedItem(name)
- setNamedItem(name)
- item(pos)
為特性設定新值:
element.attributes["id"].nodeValue = "someOtherId";
建立元素
document.createElement()方法。
引數是要建立元素的標籤名。HTML忽略大小寫,XML區分大小寫。
把新元素新增到文件樹:
appendChild()、insertBefore()、replaceChild()。
注意點:
- 不能設定動態建立的
<iframe>
元素的name特性。 - 不能通過表單的reset()方法重設動態建立的
<input>
元素。 - 動態建立的type特性值為"reset"的
<button>
元素重設不了表單。 - 動態建立的一批name相同的單選框彼此毫無關係。
元素的子節點
元素可以有任意數目的子節點和後代節點。
這些子節點有可能是元素、文字節點、註釋或處理指令。
Text型別
- nodeType的值為3
- nodeName的值為"#text"
- nodeValue的值為節點所包含的文字
- parentNode是一個Element
- 不支援(沒有)子節點。
操作節點中的文字:
- 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為止的字串。
還有個length屬性
建立文字節點
document.createTextNode()方法。
規範化文字節點
normalize()方法
父節點使用,子節點中多個文字節點合併為一個。
分割文字節點
splitText()方法。
引數:一個數值代表要分割的位置。
把一個節點分為兩個。
Comment型別
- nodeType的值為8
- nodeName的值為"#comment"
- nodeValue的值是註釋的內容
- parentNode 可能是Document或Element
- 不支援(沒有)子節點。
Coment型別與Text型別繼承自相同的基類(所以,你懂的,很多前面提到的方法可以用)。
document.createComment()
CDATASection型別
只針對基於XML的文件。類似Comment,nodeType值為4。
DocumentType型別
並不常用。包含著與文件的doctype有關的所有資訊。
- nodeType的值為10
- nodeName的值為doctype的名稱
- nodeValue的值為null
- parentNode是Document
- 不支援(沒有)子節點
DocumentFragment型別
"輕量級"文件。
- nodeType值11
- nodeName:"#document-fragment"
- nodeValue:null
- parentNode:null
- 子節點可以是:Element、ProcessingInstruction、Comment、Text、CDATASection或EntityReference。
document.createDocumentFragment()方法。
Attr型別
- nodeType:2
- nodeName:特性的名稱
- nodeValue:特性的值
- parentNode:null
- 在HTML中不支援(沒有)子節點。
- 在XML中子節點可以是Text或EntityReference。
3個屬性:name、value、specified(布林值,區別在程式碼中指定的還是預設的)。
程式碼演示:
var attr = document.createAttribute("align");
attr.value = "left";
element.setAttributeNode(attr);
alert(element.atrributes["align"].value); //"left"
alert(element.getAtrributeNode("align").value); //"left"
alert(element.getAtrribute("align")); //"left"
DOM操作技術
瀏覽器中充斥著隱藏的陷阱和不相容問題。
動態指令碼
在頁面載入時不存在,但將來的某一時刻通過修改DOM動態新增的指令碼。
建立動態指令碼兩種方式:插入外部檔案和直接插入JavaScript程式碼。
封裝的方法實現載入外部JavaScript檔案:
function loadScript(url) {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = url;
document.body,appendChild(script);
}
直接插入封裝的函式:
function loadScriptString(code) {
var script = document.createElement("script");
script.type = "text/javascript";
try {
script.appendChild(document.createTextNode(code));
}catch(ex) {
script.text = code;
}
document.body.appendChild(script);
}
動態樣式
封裝的載入樣式的方法:
function loadStyles(url) {
var link = document.createElement("link");
link.rel = "stylessheet";
link.type = "text/css";
link.href = url;
var head = document.getElementsByTagName("head")[0];
head.appendChild(link);
}
直接寫程式碼封裝的方法:
function loadStylesString(css) {
var style = document.createElement("style");
style.type = "text/css";
try {
style.appendChild(document.createTextNode(css));
} catch (ex) {
style.styleSheet.cssText = css;
}
var head = document.getElementsByTagName('head')[0];
head.appendChild(style);
}
操作表格
<table>
元素是HTML中最複雜的結構之一。
正常寫需要冗長的程式碼。
使用HTMLDOM提供的方法可以簡化。
例:要建立下面結構:
<table border="1" width="100%">
<tbody>
<tr>
<td>Cell 1,1</td>
<td>Cell 2,1</td>
</tr>
<tr>
<td>Cell 1,2</td>
<td>Cell 2,2</td>
</tr>
</tbody>
</table>
DOM程式碼:
//建立table
var table = document.createElement("table");
table.border = 1;
table.width = "100%";
//建立tbody
var tbody = document.createElement("tbody");
table.appendChild(tbody);
//建立第一行
tbody.insertRow(0);
tbody.rows[0].insertCell(0);
tbody.rows[0].cells[0].appendChild(document.createTextNode("Cell 1,1"));
tbody.rows[0].insertCell(1);
tbody.rows[0].cells[1].appendChild(document.createTextNode("Cell 2,1"));
//建立第二行
tbody.insertRow(1);
tbody.rows[1].insertCell(0);
tbody.rows[1].cells[0].appendChild(document.createTextNode("Cell 1,2"));
tbody.rows[1].insertCell(1);
tbody.rows[1].cells[1].appendChild(document.createTextNode("Cell 2,2"));
//將表格新增到文件主體中
document.body.appendChild(table);
使用NodeList
三個”動態的”集合:NameNodeMap、HTMLCollection和NodeList。
每當文件結構發生變化時,都會得到更新。