節(jié)點層次
DOM 可以將任何 HTML 和 XML 文檔描繪成一個由多層節(jié)點構(gòu)成的結(jié)構(gòu)。節(jié)點分為幾種不同的類型搂捧,每種類型分別表示文檔中不同的信息和標(biāo)記扮宠。每個節(jié)點都擁有各自的特點抛虫、數(shù)據(jù)和方法松靡,另外也與其他節(jié)點存在某種關(guān)系。節(jié)點之間的關(guān)系構(gòu)成了層次建椰,而所有頁面標(biāo)記則表現(xiàn)為一個以特定節(jié)點為根節(jié)點的樹形結(jié)構(gòu)雕欺。
-
Node 類型
- DOM1 級定義了一個 Node 接口,該接口將由 DOM 中的所有節(jié)點類型實現(xiàn)棉姐。這個 Node 接口在 JavaScript 中是作為 Node 類型實現(xiàn)的屠列;除了 IE 之外,在其他所有瀏覽器中都可以訪問到這個類型伞矩。JavaScript 中的所有節(jié)點類型都繼承自 Node 類型笛洛,因此所有節(jié)點類型由在 Node 類型中定義的下列 12 個數(shù)值常量表示:
- Node.ELEMENT_NODE(1);
- Node.ATTRIBUTE_NODE(2);
- Node.TEXT_NODE(3);
- Node.CDATA_SELECTION_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);
- 將 nodeType 屬性與數(shù)字值進行比較,可以確定節(jié)點的類型乃坤。
if(someNode.nodeType == 1) { alert('Is a Element'); }
- 詳細信息:
-
nodeName 和 nodeValue 屬性
- 對于元素節(jié)點苛让,nodeName 中保存的始終都是元素的標(biāo)簽名,而 nodeValue 的值則始終為 null湿诊。
-
節(jié)點關(guān)系
- 每一個節(jié)點都有一個 childNodes 屬性狱杰,其中保存著一個 NodeList 對象。NodeList 是一種類數(shù)組對象厅须,用于保存一組有序的節(jié)點仿畸,可以通過位置來訪問這些節(jié)點。但是朗和,NodeList 不是 Array 的實例错沽,它實際上是基于 DOM 結(jié)構(gòu)動態(tài)執(zhí)行查詢的結(jié)果,因此 DOM 結(jié)構(gòu)的變化能夠自動反映在 NodeList 對象中例隆。由于 IE8 及更早版本將 NodeList 實現(xiàn)為一個 COM 對象,所以不能使用正常的操作方法操作這種對象抢蚀。必須手動枚舉 NodeList 中的所有成員
function convertToArray(nodes) { var array = null; try { array = Array.prototype.slice.call(nodes, 0); } catch (ex) { array = new Array(); for(var i = 0, len = nodes.length; i < len; i++) { array.push(nodes[i]); } } return array; }
- 每一個節(jié)點都有一個 parentNode 屬性镀层,該屬性指向文檔樹種的父節(jié)點。包含在 childNodes 列表中的所有節(jié)點都具有相同的父節(jié)點,因此它們的 parentNode 屬性都指向同一個節(jié)點唱逢。包含在 childNodes 列表中的每個節(jié)點相互之間都是同胞節(jié)點吴侦。通過使用列表中每個節(jié)點的 previousSibling 屬性和 nextSibling 屬性,可以訪問同一列表中的其他節(jié)點坞古。
- 父節(jié)點的 firstChild 和 lastChild 屬性分別指向其 childNodes 列表中的第一個和最后一個節(jié)點备韧。
- hasChildNodes() 在節(jié)點包含一個或多個子節(jié)點的情況下返回 true。(比查詢 length 更簡單)
- ownerDocument 屬性指向表示整個文檔的文檔節(jié)點痪枫。任何節(jié)點都屬于它所在的文檔织堂,任何節(jié)點都不能同時存在于兩個或多個文檔中。用此屬性可以直接訪問文檔節(jié)點奶陈。
-
操作節(jié)點
- appendChild() 用于向 childNodes 列表的末尾添加一個節(jié)點易阳。添加節(jié)點后,childNodes 的新增節(jié)點吃粒、父節(jié)點及以前的最后一個子節(jié)點的關(guān)系指針都會相應(yīng)地得到更新潦俺。更新完成后,appendChild() 返回新增的節(jié)點徐勃。
- 任何 DOM 節(jié)點都不能同時出現(xiàn)在文檔中的多個位置上事示。因此,如果在調(diào)用 appendChild() 時傳入了父節(jié)點的第一個子節(jié)點僻肖,那么該節(jié)點就會成為父節(jié)點的最后一個子節(jié)點肖爵。
- insertBefore() 將節(jié)點放在 childNodes 列表中某個特定的位置上。接收兩個參數(shù):要插入的節(jié)點和作為參照的節(jié)點檐涝。要插入的節(jié)點會作為變成參照節(jié)點的前一個同胞節(jié)點(previousSibling)遏匆,同時被方法返回。如果參照節(jié)點是 null 谁榜,則與 appendChild() 相同幅聘。
- replaceChild() 替換節(jié)點。接收兩個參數(shù):要插入的節(jié)點和要被替換的節(jié)點窃植。將由這個方法刪除要被替換的節(jié)點帝蒿,同時由要插入的節(jié)點占據(jù)其位置。
- removeChild() 移除節(jié)點巷怜。返回被移除的節(jié)點葛超。
-
其他方法
- cloneNode() 用于創(chuàng)建調(diào)用這個方法的節(jié)點的一個完全相同的副本。接收一個 boolean 類型參數(shù)延塑,表示是否執(zhí)行深復(fù)制(復(fù)制節(jié)點及其整個子節(jié)點樹)绣张。如果是 false 執(zhí)行淺復(fù)制(只復(fù)制節(jié)點本身)。
- normalize() 處理文檔樹中的文本節(jié)點关带。當(dāng)在某個節(jié)點上調(diào)用這個方法時侥涵,就會在該節(jié)點的后代節(jié)點中查找上述兩種情況。如果找到了空文本節(jié)點則刪除它;如果找到了相鄰的文本節(jié)點芜飘,則將它們合并為一個文本節(jié)點务豺。
-
- DOM1 級定義了一個 Node 接口,該接口將由 DOM 中的所有節(jié)點類型實現(xiàn)棉姐。這個 Node 接口在 JavaScript 中是作為 Node 類型實現(xiàn)的屠列;除了 IE 之外,在其他所有瀏覽器中都可以訪問到這個類型伞矩。JavaScript 中的所有節(jié)點類型都繼承自 Node 類型笛洛,因此所有節(jié)點類型由在 Node 類型中定義的下列 12 個數(shù)值常量表示:
-
Document 類型
- 在瀏覽器中,document 對象是 HTMLDocument(繼承自 Document 類型)的一個實例嗦明,表示整個 HTML 頁面笼沥。
- Document 節(jié)點具有如下特征:
- nodeType 9
- nodeName '#document'
- nodeValue null
- parentNode null
- ownerDocument null
- 子節(jié)點可能是一個 DocumentType(最多一個)、Element(最多一個)娶牌、ProcessingInstruction 或 Comment 奔浅。
- Document 類型可以表示 HTML 頁面或者其他基于 XML 的文檔。最常見的應(yīng)用還是作為 HTMLDocument 實例的 document 對象裙戏。
- Document 節(jié)點有兩個內(nèi)置的訪問其子節(jié)點的快捷方式:documentElement 屬性乘凸,始終指向 HTML 頁面中的 <html> 元素;通過 childNodes 列表訪問文檔元素累榜。
- 作為 HTMLDocument 的實例营勤,document 對象還有一個 body 屬性,直接指向 <body> 元素壹罚。
- Document 另一個可能的子節(jié)點是 DocumentType葛作。通常將 <!DOCTYPE> 標(biāo)簽看成一個與文檔其他部分不同的實體,可以通過 doctype 屬性(在瀏覽器中是 document.doctype )來訪問它的信息猖凛。但是在 IE8 中會將 DOCTYPE 作為注釋赂蠢,所以 doctype 值始終為 null。
- document 的其他標(biāo)準(zhǔn)屬性
- title 包含 <title> 元素中的文本辨泳。
- URL 包含頁面完整的 URL虱岂。
- domain 包含頁面的域名。
- referrer 保存著鏈接到當(dāng)前頁面的那個頁面的 URL菠红;在沒有來源頁面的情況下第岖,referrer 屬性可能包含空字符串。
- 查找元素
- getElementById()
- getElementsByTagName()
- IE8 以下试溯,元素 ID 不區(qū)分大小寫蔑滓。
- namedItem() 通過元素的 name 特性取得集合中的項。(也可以使用 [] 進行訪問)
- 調(diào)用 document.getElementsByTagName('*') 取得文檔中的所有元素遇绞。
- (只有 HTMLDocument 才有)getElementsByName() (如果使用 namedItem() 只會取得所有與傳入 name 吻合的元素中的第一個元素)
- 特殊集合
- document.anchors
- document.applets
- document.forms
- document.images
- document.links
- DOM 一致性檢測
- document.implementation 檢測瀏覽器實現(xiàn)了 DOM 的哪些部分键袱。
- DOM1 只為 document.implementation 規(guī)定了 hasFeature(),接受兩個參數(shù):要檢測的 DOM 功能的名稱及版本號摹闽。如果瀏覽器支持給定名稱和版本的功能蹄咖,則返回 true。(查文檔)
- document.implementation 檢測瀏覽器實現(xiàn)了 DOM 的哪些部分键袱。
- 文檔寫入
- write() / writeln() 接收一個字符串參數(shù)付鹿,即要寫入到輸出流中的文本澜汤。
- 在文檔加載結(jié)束后調(diào)用 document.write() 那么輸出的內(nèi)容將會重寫整個頁面铝量。
- open() / close() 打開 / 關(guān)閉 當(dāng)前網(wǎng)頁的輸出流。如果在頁面加載期間使用 write() / writeln()银亲,則不需要使用這兩個方法。
- write() / writeln() 接收一個字符串參數(shù)付鹿,即要寫入到輸出流中的文本澜汤。
-
Element 類型
-
Element 類型用于表現(xiàn) XML 或 HTML 元素纽匙,提供了對元素標(biāo)簽名务蝠、子節(jié)點及特性的訪問。Element 節(jié)點具有以下特性:
- nodeType 1
- nodeName 元素標(biāo)簽名
- nodeValue null
- parentNode 可能是 Document 可能是 null
- 其他子節(jié)點可能是 Element Text Comment ProcessingInstruction CDATASection EntityReference
訪問元素的標(biāo)簽名烛缔,可以使用 nodeName 也可以使用 tagName馏段。(在 HTML 中,標(biāo)簽名始終以全部大寫表示践瓷,而 XML 則始終與源代碼中保持一致院喜。)
HTML 元素的關(guān)聯(lián)關(guān)系(查手冊)
-
取得特性(不區(qū)分大小寫)
- getAttribute()
-
設(shè)置特性
- setAttribute()
- removeAttribute()
-
attributes 屬性
- Element 類型是使用 attributes 屬性的唯一一個 DOM 類型節(jié)點。attributes 屬性中包含一個 NamedNodeMap晕翠,與 NodeList 類似喷舀,也是一個”動態(tài)“的集合。元素的每一個特性都由一個 Attr 節(jié)點表示淋肾,每個節(jié)點都保存在 NamedNodeMap 對象中硫麻。NamedNodeMap 對象擁有下列方法:
- getNamedItem(name) 返回 nodeName 屬性等于 name 的節(jié)點;
- removeNamedItem(name) 從列表中移除 nodeName 屬性等于 name 的節(jié)點樊卓;
- setNamedItem(node) 向列表中添加節(jié)點拿愧,以節(jié)點的 nodeName 屬性為索引;
- item(pos) 返回位于數(shù)字 pos 位置處的節(jié)點碌尔。
- attribute 屬性中包含一系列節(jié)點浇辜,每個節(jié)點的 nodeName 就是特性的名稱,而節(jié)點的 nodeValue 就是特性的值唾戚。要取得元素的 id 特性柳洋,可以使用如下代碼:
var id = element.attributes.getNamedItem('id').nodeValue; var id_1 = element.attributes['id'].nodeValue;
- 在 IE7- 中,所有被指定的特性或者通過 setAttribute() 設(shè)置的特性颈走,其 specified 屬性值都會變成 true膳灶。
-
創(chuàng)建元素
- document.createElement() 接收一個參數(shù):要創(chuàng)建元素的標(biāo)簽名或完整標(biāo)簽。
var div = document.createElement('div'); var newDiv = document.createElement('<div id=\"myNewDiv\" class=\"box\"></div>');
-
元素的子節(jié)點
- 元素可以有任意數(shù)目的子節(jié)點和后代節(jié)點立由。
- 元素支持 getElementsByTagName() 方法轧钓。在通過元素調(diào)用這個方法時,除了搜索起點是當(dāng)前元素之外锐膜,其他方面都跟通過 document 調(diào)用這個方法相同毕箍,因此結(jié)果只會返回當(dāng)前元素的后代。
-
-
Text 類型
-
文本節(jié)點由 Text 類型表示道盏,包含的是可以照字面解釋的純文本內(nèi)容而柑。純文本中可以包含轉(zhuǎn)義后的 HTML 字符文捶,但不能包含 HTML 代碼。Text 節(jié)點具有以下特征:
- nodeType 3
- nodeName '#text'
- nodeValue 節(jié)點所包含的文本
- parentNode Element
- 不支持(沒有)子節(jié)點
- 可以通過 nodeValue 或 data 屬性訪問 Text 節(jié)點中包含的文本媒咳,這兩個屬性中包含的值相同粹排。對 nodeValue 的修改也會通過 data 反映出來,反之亦然涩澡。
- appendData(text) 將 text 添加到節(jié)點末尾
- deleteData(offset, count) 從 offset 指定的位置開始刪除 count 個字符顽耳。
- insertData(offset, text) 在 offset 指定的位置插入 text
- replaceData(offset, count, text) 用 text 替換從 offset 指定的位置開始到 offset + count 為止處的文本。
- splitText(offset) 從 offset 指定的位置將當(dāng)前文本節(jié)點分成兩個文本節(jié)點妙同。
- subStringData(offset, count) 提取從 offset 指定的位置開始到 offset + count 位置處的字符串射富。
- length 保存節(jié)點中字符的數(shù)目。(nodeValue.length == data.length)
- 每個可以包含內(nèi)容的元素最多只能有一個文本節(jié)點粥帚,而且必須確實有內(nèi)容存在胰耗。
-
創(chuàng)建文本節(jié)點
- document.createTextNode() 接收一個參數(shù):要插入節(jié)點中的文本。
- 在創(chuàng)建文本節(jié)點時芒涡,也會為其設(shè)置 ownerDocument 屬性柴灯。不過,除非把新節(jié)點添加到文檔樹中已經(jīng)存在的節(jié)點中费尽,否則不會在瀏覽器窗口中看到新的節(jié)點弛槐。
var element = document.createElement('div'); element.className = 'message'; var textNode = document.createTextNode('<strong>Hello</strong> world!'); element.appendChild(textNode); document.body.appendChild(element);
-
規(guī)范化文本節(jié)點
- 合并相鄰文本節(jié)點,由 Node 類型定義依啰,名叫 normalize()乎串。如果在一個包含兩個或者多個文本節(jié)點的父元素上調(diào)用 normalize() 方法,則會將所有文本節(jié)點合并成一個節(jié)點速警,結(jié)果節(jié)點的 nodeValue 值等于將合并前每個文本節(jié)點的 nodeValue 值拼接起來的值叹誉。
var element = document.createElement('div'); element.className = 'message'; var textNode = document.createTextNode('Hello'); var anotherTextNode = document.createTextNode('World'); element.appendChild(textNode); element.appendChild(anotherTextNode); element.normalize();
-
分割文本節(jié)點
- splitText() 將一個文本節(jié)點分成兩個文本節(jié)點,按照指定的位置分割 nodeValue 值闷旧。原文本節(jié)點將包含從頭開始到指定位置之前的內(nèi)容长豁,新的文本節(jié)點包含剩下的文本。該方法返回一個新的文本節(jié)點忙灼,該節(jié)點與原節(jié)點的 parentNode 相同匠襟。
var element = document.createElement('div'); element.className = 'message'; var textNode = document.createTextNode('Hello World'); element.appendChild(textNode); document.body.appendChild(element); var newNode = element.firstChild.splitText(5);
-
-
Comment 類型
- 注釋在 DOM 中是通過 Comment 類型來表示的。Comment 節(jié)點具有下列特征:
- nodeType 8
- nodeName '#comment'
- nodeValue 注釋內(nèi)容
- parentNode Document / Element
- 不支持子節(jié)點
- 與 Text 類型繼承自相同的基類该园,擁有除 splitText 外所有字符串的操作方法酸舍。與 Text 類型相似,也可以通過 nodeValue 或 data 屬性取得注釋內(nèi)容里初。
- 使用 document.createComment() 并為其傳遞注釋文本可以創(chuàng)建注釋節(jié)點啃勉。
- 注釋在 DOM 中是通過 Comment 類型來表示的。Comment 節(jié)點具有下列特征:
-
CDATASection 類型
- CDATASection 類型值針對基于 XML 的文檔,表示 CDATA 區(qū)域双妨。CDATASection 節(jié)點具有下列特征:
- nodeType 4
- nodeName "#cdata-section"
- nodeValue CDATA 區(qū)域中的內(nèi)容
- parentNode Document / Element
- 與 Text 類型吧繼承自相同的基類淮阐,擁有除 splitText 外所有字符串的操作方法叮阅。
- CDATA 區(qū)域只會出現(xiàn)在 XML 文檔中,因此多數(shù)瀏覽器會把 CDATA 區(qū)域錯誤的解析為 Comment 或 Element泣特。在真正的 XML 文檔中浩姥,可以使用 document.createCDataSection() 來創(chuàng)建 CDATA 區(qū)域。
- CDATASection 類型值針對基于 XML 的文檔,表示 CDATA 區(qū)域双妨。CDATASection 節(jié)點具有下列特征:
-
DocumentType 類型
- 僅有 Firefox状您、Safari及刻、Opera 支持。包含于文檔的 doctype 有關(guān)的所有信息竞阐。具有如下特征:
- nodeType 10
- nodeName doctype 的名稱
- nodeValue null
- parentNode Document
- 在 DOM1 中,DocumentType 對象智能通過解析文檔代碼的方式來創(chuàng)建暑劝。支持它的瀏覽器會把 DocumentType 對象保存在 document.doctype 中骆莹。DOM1 描述了 DocumentType 的三個屬性:name entities notations。
- 僅有 Firefox状您、Safari及刻、Opera 支持。包含于文檔的 doctype 有關(guān)的所有信息竞阐。具有如下特征:
-
DocumentFragment 類型
- DocumentFragment 在文檔中沒有對應(yīng)的標(biāo)記担猛。DOM 規(guī)定文檔片段 (document fragment) 是一種”輕量級“的文檔幕垦,可以包含和控制節(jié)點,但不會像完整的文檔那樣占用額外的資源傅联。DocumentFragment 節(jié)點具有下列特征:
- nodeType 11
- nodeName "#document-fragment"
- nodeValue null
- parentNode null
- 子節(jié)點可以是 Element ProcessingInstruction Comment Text CDATASection 或 EntityReference
- 創(chuàng)建 DocumentFragment 對象可以使用 document.createDocumentFragment() 方法先改。
- DocumentFragment 繼承了 Node 的所有方法≌糇撸可以通過 appendChild() 或 insertChild() 將文檔片段中的內(nèi)容添加到文檔中仇奶。將文檔片段作為參數(shù)傳遞給這兩個方法時,實際上只會將文檔片段的所有子節(jié)點添加到相應(yīng)位置上比驻;文檔片段本身永遠不會稱為文檔樹的一部分该溯。
- DocumentFragment 在文檔中沒有對應(yīng)的標(biāo)記担猛。DOM 規(guī)定文檔片段 (document fragment) 是一種”輕量級“的文檔幕垦,可以包含和控制節(jié)點,但不會像完整的文檔那樣占用額外的資源傅联。DocumentFragment 節(jié)點具有下列特征:
-
Attr 類型
- 元素的特性在 DOM 中以 Attr 類型來表示。在所有瀏覽器中都可以訪問 Attr 類型的構(gòu)造函數(shù)和原型别惦。從技術(shù)角度來講狈茉,特性就是存在于元素的 attributes 屬性中的節(jié)點。特性節(jié)點具有下列特征:
- nodeType 2
- nodeName 特性名稱
- nodeValue 特性的值
- parentNode null
- Attr 對象有三個屬性掸掸,name value specified氯庆。其中,name 是特性名稱扰付,value 是特性的值堤撵,specified 是布爾值,用以區(qū)別特性是代碼中指定的還是默認(rèn)的羽莺。
- 使用 document.createAttribute() 并傳入特性的名稱可以創(chuàng)建新的特性節(jié)點粒督。
var attr = document.createAttribute('align'); attr.value = 'left'; element.setAttributeNode(attr);
- 元素的特性在 DOM 中以 Attr 類型來表示。在所有瀏覽器中都可以訪問 Attr 類型的構(gòu)造函數(shù)和原型别惦。從技術(shù)角度來講狈茉,特性就是存在于元素的 attributes 屬性中的節(jié)點。特性節(jié)點具有下列特征:
DOM 操作技術(shù)
-
動態(tài)腳本
動態(tài)腳本指的是在頁面加載時不存在,但是將來的某個時刻通過修改 DOM 動態(tài)添加的腳本禽翼。
-
創(chuàng)建動態(tài)腳本可以插入外部文件屠橄,也可以直接插入 JavaScript 代碼族跛。
<script type="text/javascript" src="client.js"></script>
動態(tài)創(chuàng)建這個節(jié)點的 DOM
var script = document.createElement("script"); script.type = "text/javascript"; script.src = "client.js"; document.body.appendChild(script);
行內(nèi) JavaScript 代碼也可以使用類似的方式添加。
使用這種方式要考慮兼容性問題锐墙。
以這種方式加載的代碼會在全局作用域中執(zhí)行礁哄,而且當(dāng)腳本執(zhí)行后立即可用。實際上溪北,這樣執(zhí)行的代碼與在全局作用域中把相同的字符串傳遞給 eval() 是一樣的桐绒。
-
動態(tài)樣式
- 方法類似于動態(tài)腳本。
- 必須將 <link> 元素添加到 <head> 而不是 <body> 中之拨,才能保證在所有瀏覽器中的行為一致茉继。
- 加載樣式與執(zhí)行 JavaScript 代碼是異步的,后邊的章節(jié)給出了利用時間檢測這個過程是否完成的方法蚀乔。
- IE 將 <style> 視為一個特殊的烁竭、與 <script> 類似的節(jié)點,不允許訪問其子節(jié)點吉挣。通過訪問元素的 styleSheet 屬性中的 cssText 屬性可以使其接受 CSS 代碼派撕。
var style = document.createElement("style"); style.type = "text/css"; try { style.appendChild(document.createTextNode("body {background-color: red}")); } catch (ex) { style.styleSheet.cssText = "body {background-color: red}"; var head = document.getElementByTagName("head")[0]; head.appendChild(style);
-
表格操作
- DOM 為 <table> <tbody> <tr>元素添加了一些屬性和方法,以方便表格的創(chuàng)建睬魂。(查手冊)
-
使用 NodeList
- 每當(dāng)文檔結(jié)構(gòu)發(fā)生變化時终吼,NodeList NamedNodeMap 和 HTMLCollection 都會得到更新。從本質(zhì)上說氯哮,所有的 NodeList 對象都是在訪問 DOM 文檔時實時運行的查詢际跪。
- 使用迭代方法對 NodeList 進行操作時,最好使用第二個變量保存 NodeList 的 length喉钢。