原文 鏈接
一、基本類(lèi)型介紹
1.1 Node類(lèi)型
-
DOM1
級(jí)定義了一個(gè)Node
接口,該接口由DOM
中所有節(jié)點(diǎn)類(lèi)型實(shí)現(xiàn)。這個(gè)Node
接口在JS
中是作為Node
類(lèi)型實(shí)現(xiàn)的。在IE9
以下版本無(wú)法訪問(wèn)到這個(gè)類(lèi)型,JS
中所有節(jié)點(diǎn)都繼承自Node
類(lèi)型,都共享著相同的基本屬性和方法 -
Node
有一個(gè)屬性nodeType
表示Node
的類(lèi)型,它是一個(gè)整數(shù),其數(shù)值分別表示相應(yīng)的Node
類(lèi)型
- 假設(shè)我們要判斷一個(gè)
Node
是不是元素,我們可以這樣判斷
if(someNode.nodeType == 1){
console.log("Node is a element");
}
- 這些
Node
類(lèi)型中,我們最常用的就是element
,text
,attribute
,comment
,document
,document_fragment
這幾種類(lèi)型
1.2 Element類(lèi)型
Element
提供了對(duì)元素標(biāo)簽名,子節(jié)點(diǎn)和特性的訪問(wèn),我們常用HTML
元素比如div
,span
,a
等標(biāo)簽就是element
中的一種。-
Element
有下面幾條特性:-
nodeType
為1
-
nodeName
為元素標(biāo)簽名,tagName
也是返回標(biāo)簽名 -
nodeValue
為null
-
parentNode
可能是Document
或Element
- 子節(jié)點(diǎn)可能是
Element
,Text
,Comment
,Processing_Instruction
,CDATASection
或EntityReference
-
1.3 Text類(lèi)型
-
Text
表示文本節(jié)點(diǎn),它包含的是純文本內(nèi)容,不能包含html
代碼,但可以包含轉(zhuǎn)義后的html
代碼。Text
有下面的特性:-
nodeType
為3
-
nodeName
為#text
-
nodeValue
為文本內(nèi)容 -
parentNode
是一個(gè)Element
- 沒(méi)有子節(jié)點(diǎn)
-
1.4 Attr類(lèi)型
-
Attr
類(lèi)型表示元素的特性,相當(dāng)于元素的attributes
屬性中的節(jié)點(diǎn),它有下面的特性:-
nodeType
值為2 -
nodeName
是特性的名稱(chēng) -
nodeValue
是特性的值 -
parentNode
為null
-
1.5 Comment類(lèi)型
-
Comment
表示HTML
文檔中的注釋?zhuān)邢旅娴膸追N特征:-
nodeType
為8 -
nodeName
為#comment
-
nodeValue
為注釋的內(nèi)容 -
parentNode
可能是Document
或Element
- 沒(méi)有子節(jié)點(diǎn)
-
1.6 Document
-
Document
表示文檔,在瀏覽器中,document
對(duì)象是HTMLDocument
的一個(gè)實(shí)例,表示整個(gè)頁(yè)面,它同時(shí)也是window
對(duì)象的一個(gè)屬性。Document
有下面的特性:-
nodeType
為9
-
nodeName
為#document
-
nodeValue
為null
-
parentNode
為null
- 子節(jié)點(diǎn)可能是一個(gè)
DocumentType
或Element
-
1.7 DocumentFragment類(lèi)型
-
DocumentFragment
是所有節(jié)點(diǎn)中唯一一個(gè)沒(méi)有對(duì)應(yīng)標(biāo)記的類(lèi)型,它表示一種輕量級(jí)的文檔,可能當(dāng)作一個(gè)臨時(shí)的倉(cāng)庫(kù)用來(lái)保存可能會(huì)添加到文檔中的節(jié)點(diǎn)。DocumentFragment
有下面的特性:-
nodeType
為11
-
nodeName
為#document-fragment
-
nodeValue
為null
-
parentNode
為null
-
我們簡(jiǎn)單地介紹了幾種常見(jiàn)的
Node
類(lèi)型,要記住,HTML
中的節(jié)點(diǎn)并不只是包括元素節(jié)點(diǎn),它還包括文本節(jié)點(diǎn),注釋節(jié)點(diǎn)等等。在這里我們只是簡(jiǎn)單地說(shuō)明了幾種常見(jiàn)的節(jié)點(diǎn).
二、 DOM提供的幾個(gè)屬性
2.1 childNodes屬性
- 在一棵節(jié)點(diǎn)樹(shù)上,
childNodes
屬性可以用來(lái)獲取任何一個(gè)元素的所有子節(jié)點(diǎn),它是一個(gè)包含這個(gè)元素全部子元素的數(shù)組
element.childNodes
2.2 nodeType屬性
- 節(jié)點(diǎn)之間的關(guān)系構(gòu)成了節(jié)點(diǎn)層次,
html
頁(yè)面的可以畫(huà)出一個(gè)以html
標(biāo)簽為根節(jié)點(diǎn)的樹(shù)形結(jié)構(gòu)
DOM
會(huì)把文檔看作是一棵樹(shù),同時(shí)定義了很多方法來(lái)操作這棵數(shù)中的每一個(gè)元素(節(jié)點(diǎn))
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<p>hello world!!!</p>
</body>
</html>
[圖片上傳失敗...(image-635720-1545535313683)]
- 每一個(gè)節(jié)點(diǎn)都有
nodeType
屬性
node.nodeType
-
nodeType
屬性總共有12中可能取值,但其中僅有3種有實(shí)用價(jià)值- 元素節(jié)點(diǎn)的
nodeType
屬性值是1 - 屬性節(jié)點(diǎn)的
nodeType
屬性值是2 - 文本節(jié)點(diǎn)的
nodeType
屬性值是3
- 元素節(jié)點(diǎn)的
description.firstChild.nodeValue = text;
2.3 nodeValue屬性
-
nodeValue
屬性- 如果想改變一個(gè)文本節(jié)點(diǎn)的值,那就使用
DOM
提供的nodeValue
,它用來(lái)得到一個(gè)節(jié)點(diǎn)的值node.nodeValue
- 需要注意:
nodeValue
屬性獲取對(duì)象的值時(shí),得到的并不是包含在這個(gè)段落里的文本 - nodeValue屬性不僅可以用來(lái)檢測(cè)節(jié)點(diǎn)的值,還可以設(shè)置節(jié)點(diǎn)的值
- 如果想改變一個(gè)文本節(jié)點(diǎn)的值,那就使用
2.4 firstChild和lastChild屬性
- 數(shù)組元素
childNodes[0]
有個(gè)更直觀的同義詞。無(wú)論如何,只要訪問(wèn)childNodes
數(shù)組的第一個(gè)元素,都可以把它寫(xiě)成firstChild
node.firstChild
與下面等價(jià)
node.childNodes[0]
-
DOM
還提供了一個(gè)與之對(duì)應(yīng)的lastChild
屬性
node.lastChild
三、節(jié)點(diǎn)創(chuàng)建型API
- 在這里,我將常用的
DOM
操作api
進(jìn)行分類(lèi),首先要介紹的是創(chuàng)建型的api
。這一類(lèi)型的api
,簡(jiǎn)而言之就是用來(lái)創(chuàng)建節(jié)點(diǎn)的
3.1 createElement
-
createElement
通過(guò)傳入指定的一個(gè)標(biāo)簽名來(lái)創(chuàng)建一個(gè)元素,如果傳入的標(biāo)簽名是一個(gè)未知的,則會(huì)創(chuàng)建一個(gè)自定義的標(biāo)簽,注意:IE8
以下瀏覽器不支持自定義標(biāo)簽
var div = document.createElement("div");
- 使用
createElement
要注意:通過(guò)createElement
創(chuàng)建的元素并不屬于html
文檔,它只是創(chuàng)建出來(lái),并未添加到html
文檔中,要調(diào)用appendChild
或insertBefore
等方法將其添加到HTML
文檔樹(shù)中
3.2 createTextNode
-
createTextNode
用來(lái)創(chuàng)建一個(gè)文本節(jié)點(diǎn),用法如下
var textNode = document.createTextNode("一個(gè)TextNode");
-
createTextNode
接收一個(gè)參數(shù),這個(gè)參數(shù)就是文本節(jié)點(diǎn)中的文本,和createElement
一樣,創(chuàng)建后的文本節(jié)點(diǎn)也只是獨(dú)立的一個(gè)節(jié)點(diǎn),同樣需要appendChild
將其添加到HTML
文檔樹(shù)中
3.3 cloneNode
-
cloneNode
是用來(lái)返回調(diào)用方法的節(jié)點(diǎn)的一個(gè)副本,它接收一個(gè)bool
參數(shù),用來(lái)表示是否復(fù)制子元素,使用如下:
var parent = document.getElementById("parentElement");
var parent2 = parent.cloneNode(true);// 傳入true
parent2.id = "parent2";
- 這段代碼通過(guò)
cloneNode
復(fù)制了一份parent
元素,其中cloneNode
的參數(shù)為true
,表示parent
的子節(jié)點(diǎn)也被復(fù)制,如果傳入false
,則表示只復(fù)制了parent
節(jié)點(diǎn)
<div id="parent">
我是父元素的文本
<br/>
<span>
我是子元素
</span>
</div>
<button id="btnCopy">復(fù)制</button>
var parent = document.getElementById("parent");
document.getElementById("btnCopy").onclick = function(){
var parent2 = parent.cloneNode(true);
parent2.id = "parent2";
document.body.appendChild(parent2);
}
這段代碼很簡(jiǎn)單,主要是綁定
button
事件,事件內(nèi)容是復(fù)制了一個(gè)parent
,修改其id
,然后添加到文檔中-
這里有幾點(diǎn)要注意:
- 和
createElement
一樣,cloneNode
創(chuàng)建的節(jié)點(diǎn)只是游離有html
文檔外的節(jié)點(diǎn),要調(diào)用appendChild
方法才能添加到文檔樹(shù)中 - 如果復(fù)制的元素有
id
,則其副本同樣會(huì)包含該id
,由于id
具有唯一性,所以在復(fù)制節(jié)點(diǎn)后必須要修改其id - 調(diào)用接收的
bool
參數(shù)最好傳入,如果不傳入該參數(shù),不同瀏覽器對(duì)其默認(rèn)值的處理可能不同
- 和
-
除此之外,我們還有一個(gè)需要注意的點(diǎn):
- 如果被復(fù)制的節(jié)點(diǎn)綁定了事件,則副本也會(huì)跟著綁定該事件嗎?這里要分情況討論:
- 如果是通過(guò)
addEventListener
或者比如onclick
進(jìn)行綁定事件,則副本節(jié)點(diǎn)不會(huì)綁定該事件 - 如果是內(nèi)聯(lián)方式綁定比如
- 如果是通過(guò)
- 如果被復(fù)制的節(jié)點(diǎn)綁定了事件,則副本也會(huì)跟著綁定該事件嗎?這里要分情況討論:
<div onclick="showParent()"></div>
- 這樣的話,副本節(jié)點(diǎn)同樣會(huì)觸發(fā)事件
3.4 createDocumentFragment
createDocumentFragment
方法用來(lái)創(chuàng)建一個(gè)DocumentFragment
。在前面我們說(shuō)到DocumentFragment
表示一種輕量級(jí)的文檔,它的作用主要是存儲(chǔ)臨時(shí)的節(jié)點(diǎn)用來(lái)準(zhǔn)備添加到文檔中createDocumentFragment
方法主要是用于添加大量節(jié)點(diǎn)到文檔中時(shí)會(huì)使用到。假設(shè)要循環(huán)一組數(shù)據(jù),然后創(chuàng)建多個(gè)節(jié)點(diǎn)添加到文檔中
<ul id="list"></ul>
<input type="button" value="添加多項(xiàng)" id="btnAdd" />
document.getElementById("btnAdd").onclick = function(){
var list = document.getElementById("list");
for(var i = 0;i < 100; i++){
var li = document.createElement("li");
li.textContent = i;
list.appendChild(li);
}
}
這段代碼將按鈕綁定了一個(gè)事件,這個(gè)事件創(chuàng)建了100個(gè)
li
節(jié)點(diǎn),然后依次將其添加HTML
文檔中。這樣做有一個(gè)缺點(diǎn):每次一創(chuàng)建一個(gè)新的元素,然后添加到文檔樹(shù)中,這個(gè)過(guò)程會(huì)造成瀏覽器的回流。所謂回流簡(jiǎn)單說(shuō)就是指元素大小和位置會(huì)被重新計(jì)算,如果添加的元素太多,會(huì)造成性能問(wèn)題。這個(gè)時(shí)候,就是使用createDocumentFragment了
DocumentFragment
不是文檔樹(shù)的一部分,它是保存在內(nèi)存中的,所以不會(huì)造成回流問(wèn)題。我們修改上面的代碼如下
document.getElementById("btnAdd").onclick = function(){
var list = document.getElementById("list");
var fragment = document.createDocumentFragment();
for(var i = 0;i < 100; i++){
var li = document.createElement("li");
li.textContent = i;
fragment.appendChild(li);
}
list.appendChild(fragment);
}
- 優(yōu)化后的代碼主要是創(chuàng)建了一個(gè)
fragment
,每次生成的li
節(jié)點(diǎn)先添加到fragment
,最后一次性添加到list
3.5 創(chuàng)建型API總結(jié)
-
創(chuàng)建型
api
主要包括createElement
,createTextNode
,cloneNode
和createDocumentFragment
四個(gè)方法,需要注意下面幾點(diǎn):- 它們創(chuàng)建的節(jié)點(diǎn)只是一個(gè)孤立的節(jié)點(diǎn),要通過(guò)
appendChild
添加到文檔中 -
cloneNode
要注意如果被復(fù)制的節(jié)點(diǎn)是否包含子節(jié)點(diǎn)以及事件綁定等問(wèn)題 - 使用
createDocumentFragment
來(lái)解決添加大量節(jié)點(diǎn)時(shí)的性能問(wèn)題
- 它們創(chuàng)建的節(jié)點(diǎn)只是一個(gè)孤立的節(jié)點(diǎn),要通過(guò)
四、頁(yè)面修改型API
- 前面我們提到創(chuàng)建型
api
,它們只是創(chuàng)建節(jié)點(diǎn),并沒(méi)有真正修改到頁(yè)面內(nèi)容,而是要調(diào)用appendChild
來(lái)將其添加到文檔樹(shù)中。我在這里將這類(lèi)會(huì)修改到頁(yè)面內(nèi)容歸為一類(lèi)。
修改頁(yè)面內(nèi)容的api
主要包括:appendChild
,insertBefore
,removeChild
,replaceChild
4.1 appendChild
-
appendChild
我們?cè)谇懊嬉呀?jīng)用到多次,就是將指定的節(jié)點(diǎn)添加到調(diào)用該方法的節(jié)點(diǎn)的子元素的末尾。調(diào)用方法如下:
parent.appendChild(child);
child
節(jié)點(diǎn)將會(huì)作為parent
節(jié)點(diǎn)的最后一個(gè)子節(jié)點(diǎn)appendChild
這個(gè)方法很簡(jiǎn)單,但是還有有一點(diǎn)需要注意:如果被添加的節(jié)點(diǎn)是一個(gè)頁(yè)面中存在的節(jié)點(diǎn),則執(zhí)行后這個(gè)節(jié)點(diǎn)將會(huì)添加到指定位置,其原本所在的位置將移除該節(jié)點(diǎn),也就是說(shuō)不會(huì)同時(shí)存在兩個(gè)該節(jié)點(diǎn)在頁(yè)面上,相當(dāng)于把這個(gè)節(jié)點(diǎn)移動(dòng)到另一個(gè)地方
<div id="child">
要被添加的節(jié)點(diǎn)
</div>
<br/>
<br/>
<br/>
<div id="parent">
要移動(dòng)的位置
</div>
<input id="btnMove" type="button" value="移動(dòng)節(jié)點(diǎn)" />
document.getElementById("btnMove").onclick = function(){
var child = document.getElementById("child");
document.getElementById("parent").appendChild(child);
}
- 這段代碼主要是獲取頁(yè)面上的
child
節(jié)點(diǎn),然后添加到指定位置,可以看到原本的child
節(jié)點(diǎn)被移動(dòng)到parent
中了。
這里還有一個(gè)要注意的點(diǎn):如果child
綁定了事件,被移動(dòng)時(shí),它依然綁定著該事件
4.2 insertBefore
-
insertBefore
用來(lái)添加一個(gè)節(jié)點(diǎn)到一個(gè)參照節(jié)點(diǎn)之前,用法如下
parentNode.insertBefore(newNode,refNode);
-
parentNode
表示新節(jié)點(diǎn)被添加后的父節(jié)點(diǎn) -
newNode
表示要添加的節(jié)點(diǎn) -
refNode
表示參照節(jié)點(diǎn),新節(jié)點(diǎn)會(huì)添加到這個(gè)節(jié)點(diǎn)之前
<div id="parent">
父節(jié)點(diǎn)
<div id="child">
子元素
</div>
</div>
<input type="button" id="insertNode" value="插入節(jié)點(diǎn)" />
var parent = document.getElementById("parent");
var child = document.getElementById("child");
document.getElementById("insertNode").onclick = function(){
var newNode = document.createElement("div");
newNode.textContent = "新節(jié)點(diǎn)"
parent.insertBefore(newNode,child);
}
這段代碼創(chuàng)建了一個(gè)新節(jié)點(diǎn),然后添加到
child
節(jié)點(diǎn)之前和
appendChild
一樣,如果插入的節(jié)點(diǎn)是頁(yè)面上的節(jié)點(diǎn),則會(huì)移動(dòng)該節(jié)點(diǎn)到指定位置,并且保留其綁定的事件。-
關(guān)于第二個(gè)參數(shù)參照節(jié)點(diǎn)還有幾個(gè)注意的地方:
-
refNode
是必傳的,如果不傳該參數(shù)會(huì)報(bào)錯(cuò) - 如果
refNode
是undefined
或null
,則insertBefore
會(huì)將節(jié)點(diǎn)添加到子元素的末尾
-
4.3 removeChild
-
removeChild
顧名思義,就是刪除指定的子節(jié)點(diǎn)并返回,用法如下
var deletedChild = parent.removeChild(node);
deletedChild
指向被刪除節(jié)點(diǎn)的引用,它等于node
,被刪除的節(jié)點(diǎn)仍然存在于內(nèi)存中,可以對(duì)其進(jìn)行下一步操作。注意:如果被刪除的節(jié)點(diǎn)不是其子節(jié)點(diǎn),則程序?qū)?huì)報(bào)錯(cuò)。我們可以通過(guò)下面的方式來(lái)確保可以刪除:
if(node.parentNode){
node.parentNode.removeChild(node);
}
- 通過(guò)節(jié)點(diǎn)自己獲取節(jié)點(diǎn)的父節(jié)點(diǎn),然后將自身刪除
4.4 replaceChild
-
replaceChild
用于使用一個(gè)節(jié)點(diǎn)替換另一個(gè)節(jié)點(diǎn),用法如下
parent.replaceChild(newChild,oldChild);
-
newChild
是替換的節(jié)點(diǎn),可以是新的節(jié)點(diǎn),也可以是頁(yè)面上的節(jié)點(diǎn),如果是頁(yè)面上的節(jié)點(diǎn),則其將被轉(zhuǎn)移到新的位置 -
oldChild
是被替換的節(jié)點(diǎn)
4.5 頁(yè)面修改型API總結(jié)
- 頁(yè)面修改型api主要是這四個(gè)接口,要注意幾個(gè)特點(diǎn):
- 不管是新增還是替換節(jié)點(diǎn),如果新增或替換的節(jié)點(diǎn)是原本存在頁(yè)面上的,則其原來(lái)位置的節(jié)點(diǎn)將被移除,也就是說(shuō)同一個(gè)節(jié)點(diǎn)不能存在于頁(yè)面的多個(gè)位置
- 節(jié)點(diǎn)本身綁定的事件會(huì)不會(huì)消失,會(huì)一直保留著
五、節(jié)點(diǎn)查詢型API
- 節(jié)點(diǎn)查詢型
API
也是非常常用的
5.1 document.getElementById
這個(gè)接口很簡(jiǎn)單,根據(jù)元素
id
返回元素,返回值是Element
類(lèi)型,如果不存在該元素,則返回null
-
使用這個(gè)接口有幾點(diǎn)要注意:
- 元素的
Id
是大小寫(xiě)敏感的,一定要寫(xiě)對(duì)元素的id
-
HTML
文檔中可能存在多個(gè)id
相同的元素,則返回第一個(gè)元素 - 只從文檔中進(jìn)行搜索元素,如果創(chuàng)建了一個(gè)元素并指定
id
,但并沒(méi)有添加到文檔中,則這個(gè)元素是不會(huì)被查找到的
- 元素的
5.2 document.getElementsByTagName
- 這個(gè)接口根據(jù)元素標(biāo)簽名獲取元素,返回一個(gè)即時(shí)的
HTMLCollection
類(lèi)型,什么是即時(shí)的HTMLCollection
類(lèi)型呢?
<div>div1</div>
<div>div2</div>
<input type="button" value="顯示數(shù)量" id="btnShowCount"/>
<input type="button" value="新增div" id="btnAddDiv"/>
var divList = document.getElementsByTagName("div");
document.getElementById("btnAddDiv").onclick = function(){
var div = document.createElement("div");
div.textContent ="div" + (divList.length+1);
document.body.appendChild(div);
}
document.getElementById("btnShowCount").onclick = function(){
alert(divList.length);
}
這段代碼中有兩個(gè)按鈕,一個(gè)按鈕是顯示
HTMLCollection
元素的個(gè)數(shù),另一個(gè)按鈕可以新增一個(gè)div標(biāo)簽到文檔中。前面提到HTMLCollcetion
元素是即時(shí)的表示該集合是隨時(shí)變化的,也就是是文檔中有幾個(gè)div
,它會(huì)隨時(shí)進(jìn)行變化,當(dāng)我們新增一個(gè)div
后,再訪問(wèn)HTMLCollection
時(shí),就會(huì)包含這個(gè)新增的div
-
使用document.getElementsByTagName這個(gè)方法有幾點(diǎn)要注意:
- 如果要對(duì)
HTMLCollection
集合進(jìn)行循環(huán)操作,最好將其長(zhǎng)度緩存起來(lái),因?yàn)槊看窝h(huán)都會(huì)去計(jì)算長(zhǎng)度,暫時(shí)緩存起來(lái)可以提高效率 - 如果沒(méi)有存在指定的標(biāo)簽,該接口返回的不
是null
,而是一個(gè)空的HTMLCollection
-
“*”
表示所有標(biāo)簽
- 如果要對(duì)
5.3 document.getElementsByName
getElementsByName
主要是通過(guò)指定的name
屬性來(lái)獲取元素,它返回一個(gè)即時(shí)的NodeList
對(duì)象。一般用于獲取表單元素的·name·屬性-
使用這個(gè)接口主要要注意幾點(diǎn):
- 返回對(duì)象是一個(gè)即時(shí)的
NodeList
,它是隨時(shí)變化的 - 在
HTML
元素中,并不是所有元素都有name
屬性,比如div
是沒(méi)有name
屬性的,但是如果強(qiáng)制設(shè)置div的
name`屬性,它也是可以被查找到的 - 在
IE
中,如果id
設(shè)置成某個(gè)值,然后傳入getElementsByName
的參數(shù)值和id
值一樣,則這個(gè)元素是會(huì)被找到的,所以最好不好設(shè)置同樣的值給id
和name
- 返回對(duì)象是一個(gè)即時(shí)的
5.4 document.getElementsByClassName
- 這個(gè)
API
是根據(jù)元素的class
返回一個(gè)即時(shí)的HTMLCollection
,用法如下
var elements = document.getElementsByClassName(names);
-
這個(gè)接口有下面幾點(diǎn)要注意:
- 返回結(jié)果是一個(gè)即時(shí)的
HTMLCollection
,會(huì)隨時(shí)根據(jù)文檔結(jié)構(gòu)變化 -
IE9
以下瀏覽器不支持 - 如果要獲取
2
個(gè)以上classname
,可傳入多個(gè)classname
,每個(gè)用空格相隔,例如
- 返回結(jié)果是一個(gè)即時(shí)的
var elements = document.getElementsByClassName("test1 test2");
5.5 document.querySelector和document.querySelectorAll
這兩個(gè)
api
很相似,通過(guò)css
選擇器來(lái)查找元素,注意選擇器要符合CSS
選擇器的規(guī)則首先來(lái)介紹一下
document.querySelector
document.querySelector
返回第一個(gè)匹配的元素,如果沒(méi)有匹配的元素,則返回null
。注意,由于返回的是第一個(gè)匹配的元素,這個(gè)
api
使用的深度優(yōu)先搜索來(lái)獲取元素
<div>
<div>
<span class="test">第三級(jí)的span</span>
</div>
</div>
<div class="test">
同級(jí)的第二個(gè)div
</div>
<input type="button" id="btnGet" value="獲取test元素" />
document.getElementById("btnGet").addEventListener("click",function(){
var element = document.querySelector(".test");
alert(element.textContent);
})
這個(gè)例子很簡(jiǎn)單,就是兩個(gè)
class
都包含“test”
的元素,一個(gè)在文檔樹(shù)的前面,但是它在第三級(jí),另一個(gè)在文檔樹(shù)的后面,但它在第一級(jí),通過(guò)querySelector
獲取元素時(shí),它通過(guò)深度優(yōu)先搜索,拿到文檔樹(shù)前面的第三級(jí)的元素document.querySelectorAll
的不同之處在于它返回的是所有匹配的元素,而且可以匹配多個(gè)選擇符
<div class="test">
class為test
</div>
<div id="test">
id為test
</div>
<input id="btnShow" type="button" value="顯示內(nèi)容" />
document.getElementById("btnShow").addEventListener("click",function(){
var elements = document.querySelectorAll("#test,.test");
for(var i = 0,length = elements.length;i<length;i++){
alert(elements[i].textContent);
}
})
-
這段代碼通過(guò)
querySelectorAll
,使用id
選擇器和class
選擇器選擇了兩個(gè)元素,并依次輸出其內(nèi)容。要注意兩點(diǎn):-
querySelectorAll
也是通過(guò)深度優(yōu)先搜索,搜索的元素順序和選擇器的順序無(wú)關(guān) - 返回的是一個(gè)非即時(shí)的
NodeList
,也就是說(shuō)結(jié)果不會(huì)隨著文檔樹(shù)的變化而變化
-
兼容性問(wèn)題:
querySelector
和querySelectorAll
在ie8
以下的瀏覽器不支持-
小結(jié):
-
document.getElementById
返回一個(gè)對(duì)象 -
document.getElementsByName
和document.getElementsByClasName
返回一個(gè)對(duì)象數(shù)組
-
六、節(jié)點(diǎn)關(guān)系型API
[圖片上傳失敗...(image-1d163c-1545535313683)]
- 在
html
文檔中的每個(gè)節(jié)點(diǎn)之間的關(guān)系都可以看成是家譜關(guān)系,包含父子關(guān)系,兄弟關(guān)系等等
6.1 父關(guān)系型API
-
parentNode
:每個(gè)節(jié)點(diǎn)都有一個(gè)parentNode
屬性,它表示元素的父節(jié)點(diǎn)。Element
的父節(jié)點(diǎn)可能是Element
,Document
或DocumentFragment
-
parentElement
:返回元素的父元素節(jié)點(diǎn),與parentNode
的區(qū)別在于,其父節(jié)點(diǎn)必須是一個(gè)Element
,如果不是,則返回null
6.2 兄弟關(guān)系型API
previousSibling
:節(jié)點(diǎn)的前一個(gè)節(jié)點(diǎn),如果該節(jié)點(diǎn)是第一個(gè)節(jié)點(diǎn),則為null
。注意有可能拿到的節(jié)點(diǎn)是文本節(jié)點(diǎn)或注釋節(jié)點(diǎn),與預(yù)期的不符,要進(jìn)行處理一下previousElementSibling
:返回前一個(gè)元素節(jié)點(diǎn),前一個(gè)節(jié)點(diǎn)必須是Element
,注意IE9
以下瀏覽器不支持nextSibling
previousSibling
存在兼容性問(wèn)題nextElementSibling
previousElementSibling
推薦使用
<script>
var oUl = document.getElementById('ul1');
var firstEle = oUl.firstElementChild;
var lastEle = oUl.lastElementChild;
firstEle.nextElementSibling.style.background = 'red';
lastEle.previousElementSibling.style.background = 'green';
</script>
[圖片上傳失敗...(image-2a3be4-1545535313683)]
-
nextSibling
:節(jié)點(diǎn)的后一個(gè)節(jié)點(diǎn),如果該節(jié)點(diǎn)是最后一個(gè)節(jié)點(diǎn),則為null
。注意有可能拿到的節(jié)點(diǎn)是文本節(jié)點(diǎn),與預(yù)期的不符,要進(jìn)行處理一下 -
nextElementSibling
:返回后一個(gè)元素節(jié)點(diǎn),后一個(gè)節(jié)點(diǎn)必須是Element
,注意IE9
以下瀏覽器不支持
6.3 子關(guān)系型API
-
childNodes
:- 返回一個(gè)即時(shí)的
NodeList
,表示元素的子節(jié)點(diǎn)列表,子節(jié)點(diǎn)可能會(huì)包含文本節(jié)點(diǎn),注釋節(jié)點(diǎn)等。childNodes
子節(jié)點(diǎn)列表集合(只讀屬性 有兼容性問(wèn)題 )
- 返回一個(gè)即時(shí)的
<ul id="ul1">
<li>11111</li>
<li>22222</li>
<li>3333</li>
<li>44444</li>
</ul>
<script>
var oUl = document.getElementById('ul1');
console.log(oUl.childNodes);
</script>
[圖片上傳失敗...(image-560f38-1545535313683)]
從截圖中可以看出 這段代碼中
ul
的子節(jié)點(diǎn)有9
個(gè),這說(shuō)明使用childNodes
獲取的節(jié)點(diǎn)包括了文本節(jié)點(diǎn)和元素節(jié)點(diǎn)childNodes
在低版本的ie
瀏覽器下獲取的節(jié)點(diǎn)只包括元素節(jié)點(diǎn),這就導(dǎo)致了兼容性問(wèn)題-
如何解決兼容性??
- 根據(jù)子節(jié)點(diǎn)的
nodeType
屬性值判斷
- 根據(jù)子節(jié)點(diǎn)的
for (var i=0; i<oUl.childNodes.length; i++) {
if ( oUl.childNodes[i].nodeType == 1 ) {
oUl.childNodes[i].style.background = 'red';
}
}
-
children
:- 一個(gè)即時(shí)的
HTMLCollection
,子節(jié)點(diǎn)都是Element
,IE9
以下瀏覽器不支持。children
子節(jié)點(diǎn)列表集合(只讀屬性 推薦使用 )
- 一個(gè)即時(shí)的
children
獲取的子節(jié)點(diǎn)只包含元素節(jié)點(diǎn)
for (var i = 0; i<oUl.children.length; i++){
oUl.children[i].style.background = 'red';
}
firstNode
:第一個(gè)子節(jié)點(diǎn)lastNode
:最后一個(gè)子節(jié)點(diǎn)firstChild
(firstElementChild)lastChild
(lastElementChild) 第一個(gè)子節(jié)點(diǎn) 最后一個(gè)子節(jié)點(diǎn)firstChild
、lastChild
和childNodes
同樣的存在兼容性問(wèn)題,在低版本ie
瀏覽器中只能獲取到元素節(jié)點(diǎn)firstElementChild
、lastElementChild
獲取第一個(gè)元素子節(jié)點(diǎn),最后一個(gè)元素子節(jié)點(diǎn) 推薦使用
var oUl = document.getElementById('ul1');
// oUl.firstChild.style.background = 'red';//標(biāo)準(zhǔn)瀏覽器 報(bào)錯(cuò)
// oUl.lastChild.style.background = 'red';//標(biāo)準(zhǔn)瀏覽器 報(bào)錯(cuò)
oUl.firstElementChild.style.background = 'red';
oUl.lastElementChild.style.background = 'red';
[圖片上傳失敗...(image-724b20-1545535313683)]
-
hasChildNodes
方法:可以用來(lái)判斷是否包含子節(jié)點(diǎn)
七、元素屬性型
7.1 setAttribute
-
setAttribute
:它允許我們對(duì)元素屬性值做出修改與getAttribute
一樣setAttribute
也能用于元素節(jié)點(diǎn) - 通過(guò)
setAttribute
對(duì)文檔做出修改后,在通過(guò)瀏覽器的查看源碼選項(xiàng)看到的任然是改變之前的屬性值,也就是說(shuō)setAttribue
做出的修改,不會(huì)反應(yīng)到文檔本身的源碼里 -
setAttribute
優(yōu)勢(shì)在于可以修改文檔中的任何一個(gè)屬性
element.setAttribute(name, value);
- 其中
name
是特性名,value
是特性值。如果元素不包含該特性,則會(huì)創(chuàng)建該特性并賦值。 - 如果元素本身包含指定的特性名為屬性,則可以訪問(wèn)屬性進(jìn)行賦值,比如下面兩條代碼是等價(jià)
element.setAttribute("id","test");
element.id = "test";
-
非DOM的解決方案
- 其實(shí)不用
setAttribute
也可以改變?cè)氐膶傩?/li> -
setAttribute
方法是第一級(jí)DOM
的組成部分,它可以設(shè)計(jì)任何元素節(jié)點(diǎn)的任意屬性。在第1級(jí)DOM
出現(xiàn)之前,你可以通過(guò)另外一種辦法設(shè)置大部分元素的屬性
- 其實(shí)不用
element.value = "the new value";
與下面語(yǔ)句等價(jià)
element.setAttribute("value","the new value");
7.2 getAttribute
-
getAttribute
返回指定的特性名相應(yīng)的特性值,如果不存在,則返回null
或空字符串。 -
getAttribute
不屬性doucment
對(duì)象,不能通過(guò)document
對(duì)象調(diào)用,只能通過(guò)元素節(jié)點(diǎn)對(duì)象調(diào)用 - 例如可以與
getElementsByTagName
方法合用,獲取每個(gè)p
的title
屬性
var paras = document.getElementsByTagName("p");
for(var i=0;i<para.lenght;i++){
alert(paras.getAttrtitube("title"));
}
八、表格操作
九、樣式操作
十、大小和偏移
十一、網(wǎng)上的一張思維導(dǎo)圖總結(jié)
- 參考
-
JavaScript DOM
編程藝術(shù) - 常用DOM操作
-