DOM的最小組成單位叫做節點(node),一個文檔的樹形結構(DOM樹),就是由各種不同的類型的節點組成.
對於HTML文檔,節點主要有以下六種類型:Document節點、DocumentType節點、Element節點、Attribute節點、Text節點和DocumentFragment節點。
節點 | 名稱 | 含義 |
---|---|---|
Document | 文檔節點 | 整個文檔(window.document) |
DocumentType | 文檔類型節點 | 文檔的類型(比如<!DOCTYPE html>) |
Element | 元素節點 | HTML元素(比如<body>、<a>等) |
Attribute | 屬性節點 | HTML元素的屬性(比如class=”right”) |
Text | 文本節點 | HTML文檔中出現的文本 |
DocumentFragment | 文檔碎片節點 | 文檔的片段 |
瀏覽器原生提供一個Node對象,上表所有類型的節點都是Node對象派生出來的。也就是說,它們都繼承了Node的屬性和方法。
Node節點的屬性
nodeName,nodeType
nodeName屬性返回節點的名稱,nodeType屬性返回節點的常數型.
類型 | nodeName | nodeType |
---|---|---|
DOCUMENT_NODE | document | 9 |
ELEMENT_NODE | 大寫的HTML元素名 | 1 |
ATTRIBUTE_NODE | 等同於Attr.name | 2 |
TEXT_NODE | text | 3 |
DOCUMENT_FRAGMENT_NODE | document-fragment | 11 |
DOCUMENT_TYPE_NODE | 等同於DocumentType.name | 10 |
document.querySelector('a').nodeType ===1
//true
document.querySelector('a').nodeType === Node.ELEMENT_NODE //true
兩者等價
這些屬性返回當前節點的相關節點ownerDocument, nexSibling, previousSibling, parentNode, parentElement.
(1)ownerDocument:返回當前節點所在的頂層文檔對象,即document對象
var d = p.ownerDocument;
d === document //true
(2)nextSibling:返回緊跟在當前節點後面的第一個同級節點.同一級可能是不同的標籤也是可以實現的.
(3)previousSibling:返回當前節點前面的、距離最近的同一級節點.
(4)parentNode:返回當前節點的父節點.對一個節點來說,它的父節點只可能有三種類型:element節點、document節點和documentfragment節點
如何從父節點移除指定節點
if (node.parentNode) {
node.parentNode.removeChild(node);
}
(5)parentElement:返回當前節點的父Element節點.
設置執行節點的父element節點的css屬性
if(node.parentElement) {
node.parentElement.style.color = "red";
}
textContent、nodeValue:返回當前節點的內容
(1):textContent:返回當前節點和它的所有後代節點的文本內容
//<div id="divA">This is <span>some</span> text </div>
document.getElementById("divA").textContent;
//This is some text
textContent屬性,忽略當前節點內部的HTML標籤,返回所有文本內容.
IE中,所有Element節點都有一個innerText屬性,它與textContent屬性基本相同,但有幾點區別
1.innerText受CSS影響,textcontent不受。比如,如果CSS規則隱藏(hidden)了某段文本,innerText就不會返回這段文本,textcontent則照樣返回。
2. innerText返回的文本,會過濾掉空格、換行和回車鍵,textcontent則不會。
3. innerText屬性不是DOM標準的一部分,Firefox瀏覽器甚至沒有部署這個屬性,而textcontent是DOM標準的一部分。
nodeValue:返回或設置當前節點的值,格式爲字符串.該屬性只對Text節點、Comment節點、XML文檔的CDATA節點有效,其他一律返回null
childNodes、firstNode、lastChild,返回當前節點的子節點
(1)childNodes:返回一個NodeList集合,包含當前節點的所有子節點.
(2)firstNode:返回當前節點的第一個子節點
(3)lastChild:返回當前節點的最後一個子節點
baseURI:返回一個字符串,由當前網頁的協議、域名和所在的目錄組成,表示當前網頁的絕對路徑.
通常情況下,該屬性由當前網址的URL(即window.location屬性)決定
<base href="http://www.example.com/page.html">
<base target="_blank" href="http://www.example.com/page.html">
Node節點的方法
appendChild(),hasChildNodes(),方法與子節點有關
(1)appendChild():接受一個節點對象作爲參數,將其作爲最後一個子節點,插入當前節點.
var p = document.createElement("p");
document.body.appendChild(p);
(2)hasChildNodes():結合firstChild屬性和NextSibling屬性,可以遍歷當前節點的所有後代節點.
cloneNode(),insertBefore(),removeChild(),replaceChild():與節點的操作有關
(1):cloneNode():克隆一個節點,接受一個布爾值作爲參數,表示是否克隆子節點,默認不克隆
var cloneUL = document.querySelector('ul').cloneNode(true);
(2)insertBefore():將某個節點插入當前節點的指定位置.它接受兩個參數,第一個參數是所要插入的節點,第二個參數是當前節點的一個子節點,新的節點將插在這個節點的前面
(3)removeChild():接受一個子節點作爲參數,用於從當前節點移除該節點.它返回被移除的節點.
var elemnt = document.getElementById("top");
while (element.firstChild) {
elemnt.removeChild(element.firstChild);
}
//移除所有子節點
(4)replaceChild():將一個新的節點,替換當前節點的某一個子節點.它接受兩個參數,第一個參數是用來替換的新節點,第二個參數將要被替換走的子節點。
replacedNode = parentNode.replaceChild(newChild, oldChild);
contains(), compareDocumentPosition(), isEqualNode() .用於節點的相互比較
(1)contains():接受一個節點作爲參數,返回一個布爾值,表示參數節點是否爲當前節點的後代節點。
document.body.contains(node)
(2)compareDocumentPosition():與contains方法完全一致,返回一個7個比特位的二進制值,表示參數節點與當前節點的關係。
二進制值 | 數值 | 含義 |
---|---|---|
000000 | 0 | 兩個節點相同 |
000001 | 1 | 兩個節點不在同一個文檔(即有一個節點不在當前文檔) |
000010 | 2 | 參數節點在當前節點的前面 |
000100 | 4 | 參數節點在當前節點的後面 |
001000 | 8 | 參數節點包含當前節點 |
010000 | 16 | 當前節點包含參數節點 |
100000 | 32 | 瀏覽器的私有用途 |
(3)isEqualNode():返回一個布爾值,用於檢測兩個節點是否相等.
vartargerE1 = document.getElementById("targetE1");
var firstDiv = document.getElementsByTagName("div")[0];
targetE1.isEqualNode(firstDiv)
normalize:用於清理當前節點內部的所有Text節點。它會去除空的文本節點,並且將毗鄰的文本節點合併成一個。
var wrapper = document.createElement("div");
wrapper.appendChild(document.createTextNode("Part 1 "));
wrapper.appendChild(document.createTextNode("Part 2 "));
wrapper.childNodes.length // 2
wrapper.normalize();
wrapper.childNodes.length // 1
NodeList接口, HTMLCollection接口
節點對象都是單個節點,但是有時會需要一種數據結構,能夠容納多個節點。DOM提供兩種接口,用於部署這種節點的集合:NodeList接口和HTMLCollection接口。
NodeList接口
NodeList接口有時返回一個動態集合,有時返回一個靜態集合。
var parent = document.getElementById('parent');
parent.childNodes.length // 2
parent.appendChild(document.createElement('div'));
parent.childNodes.length // 3
document.querySelectorAll方法返回的是一個靜態,DOM內部的變化,並不會實時反映在該方法的返回結果之中。
NodeList接口提供length屬性和數字索引,因此可以像數組那樣,使用數字索引取出每個節點,但是它本身並不是數組,不能使用pop或push之類數組特有的方法。
// 數組的繼承鏈
myArray --> Array.prototype --> Object.prototype --> null
// NodeList的繼承鏈
myNodeList --> NodeList.prototype --> Object.prototype --> null
從上面的繼承鏈可以看到,NodeList接口對象並不繼承Array.prototype,因此不具有數組接口提供的方法。如果要在NodeList接口使用數組方法,可以將NodeList接口對象轉爲真正的數組。
var div_list = document.querySelectorAll('div');
var div_array = Array.prototype.slice.call(div_list);
遍歷NodeList接口對象的首選方法,還是使用for循環。
for (var i = 0; i < myNodeList.length; ++i) {
var item = myNodeList[i];
}
NodeList接口提供item方法,接受一個數字索引作爲參數,返回該索引對應的成員。如果取不到成員,或者索引不合法,則返回null。
nodeItem = nodeList.item(index)
// 實例
var divs = document.getElementsByTagName("div");
var secondDiv = divs.item(1);
HTMLCollection接口
HTMLCollection接口與NodeList接口類似,也是節點的集合,但是集合成員都是Element節點.document.links、docuement.forms、document.images等屬性,返回的都是HTMLCollection接口對象。
item方法根據成員的位置參數(從0開始),返回該成員。如果取不到成員或數字索引不合法,則返回null。
namedItem方法根據成員的ID屬性或name屬性,返回該成員。如果沒有對應的成員,則返回null。
ParentNode接口,ChildNode接口
不同的節點除了繼承Node接口以外,還會繼承其他接口。ParentNode接口用於獲取當前節點的Element子節點,ChildNode接口用於處理當前節點的子節點(包含但不限於Element子節點)。
ParentNode接口
用於獲取Element子節點。Element節點、Document節點和DocumentFragment節點,部署了ParentNode接口。凡是這三類節點,都具有以下四個屬性,用於獲取Element子節點。
(1)children
children屬性返回一個動態的HTMLCollection集合,由當前節點的所有Element子節點組成。
(2)firstElementChild
(3)lastElementChild
(4)childElementCount:返回當前節點的所有Element子節點的數目。
ChildNode接口
用於處理子節點(包含但不限於Element子節點)。Element節點、DocumentType節點和CharacterData接口,部署了ChildNode接口。凡是這三類節點(接口),都可以使用下面四個方法。但是現實的情況是,除了第一個remove方法,目前沒有瀏覽器支持後面三個方法。
(1):remove 移除當前節點
(2)before(), (3)after , (4)replaceWith()
html元素
html元素是網頁的根元素,document.documentElement就指向這個元素
(1)clientWidth屬性, clientHeight屬性
返回視口(viewport)的大小
innerWidth和innerHeight包括滾動條的高度和寬度,二client不將滾動條計算在內
(2)offsetWidth屬性,offsetHeight屬性
返回html元素的寬度和高度,即網頁的總寬度和總高度
dataset屬性
用於操作HTML標籤元素的data-*屬性
tabindex屬性
用來指定,當前HTML元素節點是否被tab鍵遍歷,以及遍歷的優先級。
var b1 = document.getElementById("button1");
b1.tabIndex = 1;
如果 tabindex = -1 ,tab鍵跳過當前元素。
如果 tabindex = 0 ,表示tab鍵將遍歷當前元素。如果一個元素沒有設置tabindex,默認值就是0。
如果 tabindex 大於0,表示tab鍵優先遍歷。值越大,就表示優先級越大。
頁面位置相關屬性
offsetParent屬性,offsetTop屬性和offsetLeft屬性
- offsetParent:當前HTML元素的最靠近的、並且CSS的position屬性不等於static的父元素。
- offsetTop:當前HTML元素左上角相對於offsetParent的垂直位移。
- offsetLeft:當前HTML元素左上角相對於offsetParent的水平位移。
style屬性
用來讀寫頁面元素的行內CSS屬性
Element對象方法
(1)選擇子元素的方法
Element對象也部署了document對象的4個選擇子元素的方法,而且用法完全一樣。
- querySelector方法
- querySelectorAll方法
- getElementsByTagName方法
- getElementsByClassName方法
(2)elementFromPoint方法
用於選擇在指定座標的最上層的Element對象
(3)HTML元素的屬性相關方法
- hasAttribute():返回一個布爾值,表示Element對象是否有該屬性。
- getAttribute()
- setAttribute()
- removeAttribute()
(4)matchesSelector方法
返回一個布爾值,表示Element對象是否符合某個CSS選擇器
document.querySelector('li').matchesSelector('li:first-child')
(5)focus方法
用於將當前頁面的焦點,轉移到指定元素上
document.getElementById('my-span').focus();
table元素
表格有一些特殊的DOM操作方法。
- insertRow():在指定位置插入一個新行(tr)。
- deleteRow():在指定位置刪除一行(tr)。
- insertCell():在指定位置插入一個單元格(td)。
- deleteCell():在指定位置刪除一個單元格(td)。
- createCaption():插入標題。
- deleteCaption():刪除標題。
- createTHead():插入表頭。
- deleteTHead():刪除表頭。
table元素有以下屬性:
- caption:標題。
- tHead:表頭。
- tFoot:表尾。
- rows:行元素對象,該屬性只讀。
- rows.cells:每一行的單元格對象,該屬性只讀。
- tBodies:表體,該屬性只讀。