1 什么是DOM
文檔對(duì)象模型 (DOM) 是HTML和XML文檔的編程接口帅戒。它提供了對(duì)文檔的結(jié)構(gòu)化的表述玛歌,并定義了一種方式可以使從程序中對(duì)該結(jié)構(gòu)進(jìn)行訪問(wèn)昧港,從而改變文檔的結(jié)構(gòu)擎椰,樣式和內(nèi)容支子。
文檔對(duì)象模型 (DOM) 是對(duì)HTML文件的另一種展示,通俗地說(shuō)达舒,一個(gè)HTML 文件值朋,我們可以用編輯器以代碼的形式展示它,也可以用瀏覽器以頁(yè)面的形式展示它巩搏,同一份文件通過(guò)不同的展示方式昨登,就有了不一樣的表現(xiàn)形式。而DOM 將文檔解析為一個(gè)由節(jié)點(diǎn)和對(duì)象(包含屬性和方法的對(duì)象)組成的結(jié)構(gòu)集合贯底。簡(jiǎn)言之丰辣,它會(huì)將web頁(yè)面和腳本或程序語(yǔ)言連接起來(lái)撒强,我們可以使用腳本或者程序語(yǔ)言通過(guò)DOM 來(lái)改變或者控制web頁(yè)面。
2 如何訪問(wèn)DOM
我們可以通過(guò)JavaScript 來(lái)調(diào)用document
和window
元素的API來(lái)操作文檔或者獲取文檔的信息笙什。
3 Node
Node 是一個(gè)接口飘哨,有許多接口都從Node 繼承方法和屬性:
Document
, Element
, CharacterData (which Text, Comment, and CDATASection inherit)
, ProcessingInstruction
, DocumentFragment
, DocumentType
, Notation
, Entity
, EntityReference
敛纲。
Node 有一個(gè)nodeType
的屬性表示Node 的類型氧猬,是一個(gè)整數(shù)揍庄,不同的值代表不同的節(jié)點(diǎn)類型泌类。具體如下表所示:
節(jié)點(diǎn)類型常量
常量 | 值 | 描述 |
---|---|---|
Node.ELEMENT_NODE |
1 | 一個(gè)元素節(jié)點(diǎn)裁奇,例如 <p> 和 <div>
|
Node.TEXT_NODE |
3 |
Element 或者 Attr 中實(shí)際的文字 |
Node.PROCESSING_INSTRUCTION_NODE |
7 | 一個(gè)用于XML文檔的 ProcessingInstruction 仑荐,例如 <?xml-stylesheet ... ?> 聲明 |
Node.COMMENT_NODE |
8 | 一個(gè) Comment 節(jié)點(diǎn) |
Node.DOCUMENT_NODE |
9 | 一個(gè) Document 節(jié)點(diǎn) |
Node.DOCUMENT_TYPE_NODE |
10 | 描述文檔類型的 DocumentType 節(jié)點(diǎn)延窜。例如 <!DOCTYPE html> 就是用于 HTML5 的 |
Node.DOCUMENT_FRAGMENT_NODE |
11 | 一個(gè) DocumentFragment 節(jié)點(diǎn) |
已棄用的節(jié)點(diǎn)類型常量
常量 | 值 | 描述 |
---|---|---|
Node.ATTRIBUTE_NODE |
2 | 元素的耦合屬性书聚。在DOM4 規(guī)范里Node 接口將不再實(shí)現(xiàn)這個(gè)元素屬性 |
Node.CDATA_SECTION_NODE |
4 | 一個(gè)CDATASection 愁憔。在DOM4 規(guī)范里被移除 |
Node.ENTITY_REFERENCE_NODE |
5 | 一個(gè)XML 實(shí)體引用節(jié)點(diǎn)腕扶。在DOM4 規(guī)范里被移除 |
Node.ENTITY_NODE |
6 | 一個(gè)XML <!ENTITY ...> 節(jié)點(diǎn)。在DOM4 規(guī)范中被移除 |
Node.NOTATION_NODE |
12 | 一個(gè)XML <!NOTATION ...> 節(jié)點(diǎn)吨掌。在DOM4 規(guī)范里被移除 |
假設(shè)我們要判斷一個(gè)Node 是不是一個(gè)元素
蕉毯,通過(guò)查表可知元素
的nodeType
屬性值為1,代碼可以這么寫(xiě):
if(X.nodeType === 1){
console.log('X 是一個(gè)元素');
}
在Node 類型中思犁,比較常用的就是element
代虾,text
,comment
激蹲,document
棉磨,document_fragment
這幾種類型。
3.1 Element
Element提供了對(duì)元素標(biāo)簽名学辱,子節(jié)點(diǎn)和特性的訪問(wèn)乘瓤,我們常用HTML元素比如div
,span
策泣,a
等標(biāo)簽就是element
中的一種衙傀。Element有下面幾條特性:
(1)nodeType為1
(2)nodeName為元素標(biāo)簽名,tagName也是返回標(biāo)簽名
(3)nodeValue為null
(4)parentNode可能是Document或Element
(5)子節(jié)點(diǎn)可能是Element萨咕,Text统抬,Comment,Processing_Instruction危队,CDATASection或EntityReference
3.2 Text
Text表示文本節(jié)點(diǎn)聪建,它包含的是純文本內(nèi)容,不能包含html代碼茫陆,但可以包含轉(zhuǎn)義后的html代碼金麸。Text有下面的特性:
(1)nodeType為3
(2)nodeName為#text
(3)nodeValue為文本內(nèi)容
(4)parentNode是一個(gè)Element
(5)沒(méi)有子節(jié)點(diǎn)
3.3 Comment
Comment表示HTML文檔中的注釋,它有下面的幾種特征:
(1)nodeType為8
(2)nodeName為#comment
(3)nodeValue為注釋的內(nèi)容
(4)parentNode可能是Document或Element
(5)沒(méi)有子節(jié)點(diǎn)
3.4 Document
Document表示文檔簿盅,在瀏覽器中挥下,document
對(duì)象是HTMLDocument的一個(gè)實(shí)例揍魂,表示整個(gè)頁(yè)面,它同時(shí)也是window對(duì)象的一個(gè)屬性棚瘟。Document有下面的特性:
(1)nodeType為9
(2)nodeName為#document
(3)nodeValue為null
(4)parentNode為null
(5)子節(jié)點(diǎn)可能是一個(gè)DocumentType或Element
3.5 DocumentFragment
DocumentFragment是所有節(jié)點(diǎn)中唯一一個(gè)沒(méi)有對(duì)應(yīng)標(biāo)記的類型愉烙,它表示一種輕量級(jí)的文檔,可能當(dāng)作一個(gè)臨時(shí)的倉(cāng)庫(kù)用來(lái)保存可能會(huì)添加到文檔中的節(jié)點(diǎn)解取。DocumentFragment有下面的特性:
(1)nodeType為11
(2)nodeName為#document-fragment
(3)nodeValue為null
(4)parentNode為null
4 節(jié)點(diǎn)創(chuàng)建型API
用如其名步责,這類API是用來(lái)創(chuàng)建節(jié)點(diǎn)的
4.1 createElement
createElement
通過(guò)傳入指定的一個(gè)標(biāo)簽名來(lái)創(chuàng)建一個(gè)元素,如果傳入的標(biāo)簽名是一個(gè)未知的禀苦,則會(huì)創(chuàng)建一個(gè)自定義的標(biāo)簽蔓肯,注意:IE8以下瀏覽器不支持自定義標(biāo)簽。
語(yǔ)法
let element = document.createElement(tagName);
使用createElement
要注意:通過(guò)createElement
創(chuàng)建的元素并不屬于HTML文檔振乏,它只是創(chuàng)建出來(lái)蔗包,并未添加到HTML文檔中,要調(diào)用appendChild
或insertBefore
等方法將其添加到HTML文檔樹(shù)中慧邮。
例子:
let elem = document.createElement("div");
elem.id = 'test';
elem.style = 'color: red';
elem.innerHTML = '我是新創(chuàng)建的節(jié)點(diǎn)';
document.body.appendChild(elem);
運(yùn)行結(jié)果為:
4.2 createTextNode
createTextNode
用來(lái)創(chuàng)建一個(gè)文本節(jié)點(diǎn)
語(yǔ)法
var text = document.createTextNode(data);
createTextNode
接收一個(gè)參數(shù)调限,這個(gè)參數(shù)就是文本節(jié)點(diǎn)中的文本,和createElement
一樣误澳,創(chuàng)建后的文本節(jié)點(diǎn)也只是獨(dú)立的一個(gè)節(jié)點(diǎn)耻矮,同樣需要appendChild
將其添加到HTML文檔樹(shù)中
例子:
var node = document.createTextNode("我是文本節(jié)點(diǎn)");
document.body.appendChild(node);
運(yùn)行結(jié)果為:
4.3 cloneNode
cloneNode
返回調(diào)用該方法的節(jié)點(diǎn)的一個(gè)副本
語(yǔ)法
var dupNode = node.cloneNode(deep);
node
將要被克隆的節(jié)點(diǎn)
dupNode
克隆生成的副本節(jié)點(diǎn)
deep
(可選)是否采用深度克隆,如果為true,則該節(jié)點(diǎn)的所有后代節(jié)點(diǎn)也都會(huì)被克隆,如果為false,則只克隆該節(jié)點(diǎn)本身.
這里有幾點(diǎn)要注意:
(1)和createElement
一樣,cloneNode
創(chuàng)建的節(jié)點(diǎn)只是游離有HTML文檔外的節(jié)點(diǎn)忆谓,要調(diào)用appendChild
方法才能添加到文檔樹(shù)中
(2)如果復(fù)制的元素有id
裆装,則其副本同樣會(huì)包含該id
,由于id
具有唯一性倡缠,所以在復(fù)制節(jié)點(diǎn)后必須要修改其id
(3)調(diào)用接收的deep
參數(shù)最好傳入哨免,如果不傳入該參數(shù),不同瀏覽器對(duì)其默認(rèn)值的處理可能不同
注意
如果被復(fù)制的節(jié)點(diǎn)綁定了事件昙沦,則副本也會(huì)跟著綁定該事件嗎琢唾?這里要分情況討論:
(1)如果是通過(guò)addEventListener或者比如onclick進(jìn)行綁定事件,則副本節(jié)點(diǎn)不會(huì)綁定該事件
(2)如果是內(nèi)聯(lián)方式綁定比如:<div onclick="showParent()"></div>
盾饮,這樣的話采桃,副本節(jié)點(diǎn)同樣會(huì)觸發(fā)事件。
例子:
<body>
<div id="parent">
我是父元素的文本
<br/>
<span>
我是子元素
</span>
</div>
<button id="btnCopy">復(fù)制</button>
</body>
<script>
var parent = document.getElementById("parent");
document.getElementById("btnCopy").onclick = function(){
var parent2 = parent.cloneNode(true);
parent2.id = "parent2";
document.body.appendChild(parent2);
}
</script>
運(yùn)行結(jié)果為:
4.4 createDocumentFragment
DocumentFragments
是DOM節(jié)點(diǎn)丐谋。它們不是主DOM樹(shù)的一部分芍碧。通常的用例是創(chuàng)建文檔片段,將元素附加到文檔片段号俐,然后將文檔片段附加到DOM樹(shù)。在DOM樹(shù)中定庵,文檔片段被其所有的子元素所代替吏饿。
因?yàn)槲臋n片段存在于內(nèi)存中踪危,并不在DOM樹(shù)中,所以將子元素插入到文檔片段時(shí)不會(huì)引起頁(yè)面回流(reflow)(對(duì)元素位置和幾何上的計(jì)算)猪落。因此贞远,使用文檔片段document fragments
通常會(huì)起到優(yōu)化性能的作用。
語(yǔ)法
let fragment = document.createDocumentFragment();
例子:
<body>
<ul id="ul"></ul>
</body>
<script>
(function()
{
var start = Date.now();
var str = '', li;
var ul = document.getElementById('ul');
var fragment = document.createDocumentFragment();
for(var i=0; i<1000; i++)
{
li = document.createElement('li');
li.textContent = '第'+(i+1)+'個(gè)子節(jié)點(diǎn)';
fragment.appendChild(li);
}
ul.appendChild(fragment);
})();
</script>
運(yùn)行結(jié)果為:
4.5 節(jié)點(diǎn)創(chuàng)建型API總結(jié)
節(jié)點(diǎn)創(chuàng)建型API主要包括createElement
笨忌,createTextNode
蓝仲,cloneNode
和createDocumentFragment
四個(gè)方法,需要注意下面幾點(diǎn):
(1)它們創(chuàng)建的節(jié)點(diǎn)只是一個(gè)孤立的節(jié)點(diǎn)官疲,要通過(guò)appendChild
添加到文檔中
(2)cloneNode
要注意如果被復(fù)制的節(jié)點(diǎn)是否包含子節(jié)點(diǎn)以及事件綁定等問(wèn)題
(3)使用createDocumentFragment
來(lái)解決添加大量節(jié)點(diǎn)時(shí)的性能問(wèn)題
5 頁(yè)面修改型API
前面我們提到節(jié)點(diǎn)創(chuàng)建型API袱结,它們只是創(chuàng)建節(jié)點(diǎn),并沒(méi)有真正修改到頁(yè)面內(nèi)容途凫,而是要調(diào)用·appendChild·來(lái)將其添加到文檔樹(shù)中垢夹。我在這里將這類會(huì)修改到頁(yè)面內(nèi)容歸為一類。
修改頁(yè)面內(nèi)容的api主要包括:appendChild
维费,insertBefore
果元,removeChild
,replaceChild
犀盟。
5.1 appendChild
appendChild
我們?cè)谇懊嬉呀?jīng)用到多次而晒,就是將指定的節(jié)點(diǎn)添加到調(diào)用該方法的節(jié)點(diǎn)的子元素的末尾。
語(yǔ)法
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è)地方冯事。
如果child綁定了事件焦匈,被移動(dòng)時(shí),它依然綁定著該事件昵仅。
例子:
<body>
<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)" />
</body>
<script>
document.getElementById("btnMove").onclick = function(){
var child = document.getElementById("child");
document.getElementById("parent").appendChild(child);
}
</script>
運(yùn)行結(jié)果:
5.2 insertBefore
insertBefore
用來(lái)添加一個(gè)節(jié)點(diǎn)到一個(gè)參照節(jié)點(diǎn)之前
語(yǔ)法
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)之前
例子:
<body>
<div id="parent">
父節(jié)點(diǎn)
<div id="child">
子元素
</div>
</div>
<input type="button" id="insertNode" value="插入節(jié)點(diǎn)" />
</body>
<script>
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);
}
</script>
運(yùn)行結(jié)果:
[圖片上傳失敗...(image-986770-1525955428155)]
關(guān)于第二個(gè)參數(shù)參照節(jié)點(diǎn)還有幾個(gè)注意的地方:
(1)refNode是必傳的,如果不傳該參數(shù)會(huì)報(bào)錯(cuò)
(2)如果refNode是undefined或null摔笤,則insertBefore會(huì)將節(jié)點(diǎn)添加到子元素的末尾
5.3 removeChild
刪除指定的子節(jié)點(diǎn)并返回
語(yǔ)法
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);
}
運(yùn)行結(jié)果:
通過(guò)節(jié)點(diǎn)自己獲取節(jié)點(diǎn)的父節(jié)點(diǎn)分蓖,然后將自身刪除
5.4 replaceChild
replaceChild
用于使用一個(gè)節(jié)點(diǎn)替換另一個(gè)節(jié)點(diǎn)
語(yǔ)法
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)
例子:
<body>
<div id="parent">
父節(jié)點(diǎn)
<div id="child">
子元素
</div>
</div>
<input type="button" id="insertNode" value="替換節(jié)點(diǎn)" />
</body>
<script>
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.replaceChild(newNode,child)
}
運(yùn)行結(jié)果:
5.5 頁(yè)面修改型API總結(jié)
頁(yè)面修改型API主要是這四個(gè)接口味廊,要注意幾個(gè)特點(diǎn):
(1)不管是新增還是替換節(jié)點(diǎn)蒸甜,如果新增或替換的節(jié)點(diǎn)是原本存在頁(yè)面上的,則其原來(lái)位置的節(jié)點(diǎn)將被移除余佛,也就是說(shuō)同一個(gè)節(jié)點(diǎn)不能存在于頁(yè)面的多個(gè)位置
(2)節(jié)點(diǎn)本身綁定的事件會(huì)不會(huì)消失柠新,會(huì)一直保留著。
6 節(jié)點(diǎn)查詢型API
6.1 document.getElementById
這個(gè)接口很簡(jiǎn)單衙熔,根據(jù)元素id返回元素登颓,返回值是Element類型,如果不存在該元素红氯,則返回null
語(yǔ)法
var element = document.getElementById(id);
使用這個(gè)接口有幾點(diǎn)要注意:
(1)元素的Id是大小寫(xiě)敏感的框咙,一定要寫(xiě)對(duì)元素的id
(2)HTML文檔中可能存在多個(gè)id相同的元素,則返回第一個(gè)元素
(3)只從文檔中進(jìn)行搜索元素痢甘,如果創(chuàng)建了一個(gè)元素并指定id喇嘱,但并沒(méi)有添加到文檔中,則這個(gè)元素是不會(huì)被查找到的
例子:
<body>
<p id="para1">Some text here</p>
<button onclick="changeColor('blue');">blue</button>
<button onclick="changeColor('red');">red</button>
</body>
<script>
function changeColor(newColor) {
var elem = document.getElementById("para1");
elem.style.color = newColor;
}
</script>
運(yùn)行結(jié)果:
6.2 document.getElementsByTagName
返回一個(gè)包括所有給定標(biāo)簽名稱的元素的HTML集合HTMLCollection塞栅。 整個(gè)文件結(jié)構(gòu)都會(huì)被搜索者铜,包括根節(jié)點(diǎn)。返回的 HTML集合是動(dòng)態(tài)的, 意味著它可以自動(dòng)更新自己來(lái)保持和 DOM 樹(shù)的同步而不用再次調(diào)用document.getElementsByTagName()
語(yǔ)法
var elements = document.getElementsByTagName(name);
(1)如果要對(duì)HTMLCollection集合進(jìn)行循環(huán)操作放椰,最好將其長(zhǎng)度緩存起來(lái)作烟,因?yàn)槊看窝h(huán)都會(huì)去計(jì)算長(zhǎng)度,暫時(shí)緩存起來(lái)可以提高效率
(2)如果沒(méi)有存在指定的標(biāo)簽砾医,該接口返回的不是null拿撩,而是一個(gè)空的HTMLCollection
(3)name
是一個(gè)代表元素的名稱的字符串。特殊字符 "*" 代表了所有元素如蚜。
例子:
<body>
<div>div1</div>
<div>div2</div>
<input type="button" value="顯示數(shù)量" id="btnShowCount"/>
<input type="button" value="新增div" id="btnAddDiv"/>
</body>
<script>
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);
}
</script>
這段代碼中有兩個(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。
運(yùn)行結(jié)果:
6.3 document.getElementsByName
getElementsByName
主要是通過(guò)指定的name
屬性來(lái)獲取元素讨勤,它返回一個(gè)即時(shí)的NodeList對(duì)象
語(yǔ)法
var elements = document.getElementsByName(name)
使用這個(gè)接口主要要注意幾點(diǎn):
(1)返回對(duì)象是一個(gè)即時(shí)的NodeList箭跳,它是隨時(shí)變化的
(2)在HTML元素中晨另,并不是所有元素都有name
屬性潭千,比如div
是沒(méi)有name
屬性的,但是如果強(qiáng)制設(shè)置div
的name
屬性借尿,它也是可以被查找到的
(3)在IE中刨晴,如果id
設(shè)置成某個(gè)值,然后傳入getElementsByName
的參數(shù)值和id值一樣路翻,則這個(gè)元素是會(huì)被找到的狈癞,所以最好不好設(shè)置同樣的值給id
和name
例子:
<script type="text/javascript">
function getElements()
{
var x=document.getElementsByName("myInput");
alert(x.length);
}
</script>
<body>
<input name="myInput" type="text" size="20" /><br />
<input name="myInput" type="text" size="20" /><br />
<input name="myInput" type="text" size="20" /><br />
<br />
<input type="button" onclick="getElements()" value="How many elements named 'myInput'?" />
</body>
運(yùn)行結(jié)果:
[圖片上傳失敗...(image-6abacd-1525955428156)]
6.4 document.getElementsByClassName
這個(gè)API是根據(jù)元素的class返回一個(gè)即時(shí)的HTMLCollection
語(yǔ)法
var elements = document.getElementsByClassName(names); // or:
var elements = rootElement.getElementsByClassName(names);
-
elements
是一個(gè)實(shí)時(shí)集合,包含了找到的所有元素 -
names
是一個(gè)字符串茂契,表示要匹配的類名列表蝶桶;類名通過(guò)空格分隔 -
getElementsByClassName
可以在任何元素上調(diào)用,不僅僅是document
掉冶。調(diào)用這個(gè)方法的元素將作為本次查找的根元素
這個(gè)接口有下面幾點(diǎn)要注意:
(1)返回結(jié)果是一個(gè)即時(shí)的HTMLCollection真竖,會(huì)隨時(shí)根據(jù)文檔結(jié)構(gòu)變化
(2)IE9以下瀏覽器不支持
(3)如果要獲取2個(gè)以上classname
,可傳入多個(gè)classname
厌小,每個(gè)用空格相隔恢共,例如
var elements = document.getElementsByClassName("test1 test2");
例子:
- 獲取所有
class
為 'test' 的元素
var elements = document.getElementsByClassName('test');
- 獲取所有
class
同時(shí)包括 'red' 和 'test' 的元素
var elements = document.getElementsByClassName('red test');
- 在
id
為'main'的元素的子節(jié)點(diǎn)中,獲取所有class
為'test'的元素
var elements = document.getElementById('main').getElementsByClassName('test');
- 我們還可以對(duì)任意的HTMLCollection 使用
Array.prototype
的方法璧亚,調(diào)用時(shí)傳遞HTMLCollection 作為方法的參數(shù)讨韭。這里我們將查找到所有class
為'test'的div
元素:
var testElements = document.getElementsByClassName('test');
var testDivs = Array.prototype.filter.call(testElements, function(testElement){
return testElement.nodeName === 'DIV';;
});
6.5 document.querySelector和document.querySelectorAll
這兩個(gè)API很相似,通過(guò)css選擇器來(lái)查找元素癣蟋,注意選擇器要符合CSS選擇器的規(guī)則
- 6.5.1 document.querySelector
document.querySelector
返回第一個(gè)匹配的元素透硝,如果沒(méi)有匹配的元素,則返回null
語(yǔ)法
var element = document.querySelector(selectors);
注意疯搅,由于返回的是第一個(gè)匹配的元素濒生,這個(gè)api使用的深度優(yōu)先搜索來(lái)獲取元素。
例子:
<body>
<div>
<div>
<span class="test">第三級(jí)的span</span>
</div>
</div>
<div class="test">
同級(jí)的第二個(gè)div
</div>
<input type="button" id="btnGet" value="獲取test元素" />
</body>
<script>
document.getElementById("btnGet").addEventListener("click",function(){
var element = document.querySelector(".test");
alert(element.textContent);
})
</script>
兩個(gè)class
都包含“test”的元素秉撇,一個(gè)在文檔樹(shù)的前面甜攀,但是它在第三級(jí),另一個(gè)在文檔樹(shù)的后面琐馆,但它在第一級(jí)规阀,通過(guò)querySelector
獲取元素時(shí),它通過(guò)深度優(yōu)先搜索瘦麸,拿到文檔樹(shù)前面的第三級(jí)的元素谁撼。
運(yùn)行結(jié)果:
-
6.5.2 document.querySelectorAll
返回的是所有匹配的元素,而且可以匹配多個(gè)選擇符
語(yǔ)法
var elementList = document.querySelectorAll(selectors);
-
elementList
是一個(gè)靜態(tài)的NodeList
類型的對(duì)象 -
selectors
是一個(gè)由逗號(hào)連接的包含一個(gè)或多個(gè)CSS選擇器的字符串 - 如果
selectors
參數(shù)中包含CSS偽元素,則返回一個(gè)空的elementList
例子:
var matches = document.querySelectorAll("div.note, div.alert");
返回一個(gè)文檔中所有的class
為"note"
或者"alert"
的div
元素
<body>
<div class="test">
class為test
</div>
<div id="test">
id為test
</div>
<input id="btnShow" type="button" value="顯示內(nèi)容" />
</body>
<script>
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);
}
})
</script>
這段代碼通過(guò)querySelectorAll
,使用id選擇器和class選擇器選擇了兩個(gè)元素厉碟,并依次輸出其內(nèi)容喊巍。要注意兩點(diǎn):
(1)querySelectorAll也是通過(guò)深度優(yōu)先搜索,搜索的元素順序和選擇器的順序無(wú)關(guān)
(2)返回的是一個(gè)非即時(shí)的NodeList箍鼓,也就是說(shuō)結(jié)果不會(huì)隨著文檔樹(shù)的變化而變化
兼容性問(wèn)題:querySelector
和querySelectorAll
在ie8以下的瀏覽器不支持崭参。
運(yùn)行結(jié)果:
7 節(jié)點(diǎn)關(guān)系型API
在html文檔中的每個(gè)節(jié)點(diǎn)之間的關(guān)系都可以看成是家譜關(guān)系,包含父子關(guān)系款咖,兄弟關(guān)系等等
7.1 父關(guān)系型API
7.1.1 parentNode
每個(gè)節(jié)點(diǎn)都有一個(gè)parentNode屬性何暮,它表示元素的父節(jié)點(diǎn)。Element的父節(jié)點(diǎn)可能是Element铐殃,Document或DocumentFragment
7.1.2 parentElement
返回元素的父元素節(jié)點(diǎn)海洼,與parentNode的區(qū)別在于,其父節(jié)點(diǎn)必須是一個(gè)Element富腊,如果不是坏逢,則返回null
7.2 子關(guān)系型APPI
7.2.1 childNodes
返回一個(gè)即時(shí)的NodeList,表示元素的子節(jié)點(diǎn)列表赘被,子節(jié)點(diǎn)可能會(huì)包含文本節(jié)點(diǎn)是整,注釋節(jié)點(diǎn)等
7.2.2 children:
一個(gè)即時(shí)的HTMLCollection,子節(jié)點(diǎn)都是Element帘腹,IE9以下瀏覽器不支持
children
屬性為只讀屬性贰盗,對(duì)象類型為HTMLCollection,你可以使用elementNodeReference.children[1].nodeName
來(lái)獲取某個(gè)子元素的標(biāo)簽名稱
7.2.3 firstChild
只讀屬性返回樹(shù)中節(jié)點(diǎn)的第一個(gè)子節(jié)點(diǎn)阳欲,如果節(jié)點(diǎn)是無(wú)子節(jié)點(diǎn)舵盈,則返回 null
7.2.4 lastChild
返回當(dāng)前節(jié)點(diǎn)的最后一個(gè)子節(jié)點(diǎn)。如果父節(jié)點(diǎn)為一個(gè)元素節(jié)點(diǎn)球化,則子節(jié)點(diǎn)通常為一個(gè)元素節(jié)點(diǎn)秽晚,或一個(gè)文本節(jié)點(diǎn),或一個(gè)注釋節(jié)點(diǎn)筒愚。如果沒(méi)有子節(jié)點(diǎn)赴蝇,則返回null
7.2.5 hasChildNodes
返回一個(gè)布爾值,表明當(dāng)前節(jié)點(diǎn)是否包含有子節(jié)點(diǎn).
7.3 兄弟關(guān)系型API
7.3.1 previousSibling
返回當(dāng)前節(jié)點(diǎn)的前一個(gè)兄弟節(jié)點(diǎn),沒(méi)有則返回null
Gecko內(nèi)核的瀏覽器會(huì)在源代碼中標(biāo)簽內(nèi)部有空白符的地方插入一個(gè)文本結(jié)點(diǎn)到文檔中.因此,使用諸如Node.firstChild
和Node.previousSibling
之類的方法可能會(huì)引用到一個(gè)空白符文本節(jié)點(diǎn), 而不是使用者所預(yù)期得到的節(jié)點(diǎn)
7.3.2 previousElementSibling
previousElementSibling
返回當(dāng)前元素在其父元素的子元素節(jié)點(diǎn)中的前一個(gè)元素節(jié)點(diǎn),如果該元素已經(jīng)是第一個(gè)元素節(jié)點(diǎn),則返回null
,該屬性是只讀的。注意IE9以下瀏覽器不支持
7.3.3 nextSibling
Node.nextSibling
是一個(gè)只讀屬性巢掺,返回其父節(jié)點(diǎn)的childNodes
列表中緊跟在其后面的節(jié)點(diǎn)句伶,如果指定的節(jié)點(diǎn)為最后一個(gè)節(jié)點(diǎn),則返回null
Gecko內(nèi)核的瀏覽器會(huì)在源代碼中標(biāo)簽內(nèi)部有空白符的地方插入一個(gè)文本結(jié)點(diǎn)到文檔中.因此,使用諸如Node.firstChild
和Node.previousSibling
之類的方法可能會(huì)引用到一個(gè)空白符文本節(jié)點(diǎn), 而不是使用者所預(yù)期得到的節(jié)點(diǎn)
7.3.4 nextElementSibling
nextElementSibling
返回當(dāng)前元素在其父元素的子元素節(jié)點(diǎn)中的后一個(gè)元素節(jié)點(diǎn),如果該元素已經(jīng)是最后一個(gè)元素節(jié)點(diǎn),則返回null
,該屬性是只讀的陆淀。注意IE9以下瀏覽器不支持
8 元素屬性型API
8.1 setAttribute
設(shè)置指定元素上的一個(gè)屬性值考余。如果屬性已經(jīng)存在,則更新該值; 否則將添加一個(gè)新的屬性用指定的名稱和值
語(yǔ)法
element.setAttribute(name, value);
其中name
是特性名轧苫,value
是特性值楚堤。如果元素不包含該特性,則會(huì)創(chuàng)建該特性并賦值。
例子:
<body>
<div id="div1">ABC</div>
</body>
<script>
let div1 = document.getElementById("div1");
div1.setAttribute("align", "center");
</script>
運(yùn)行結(jié)果:
如果元素本身包含指定的特性名為屬性身冬,則可以世界訪問(wèn)屬性進(jìn)行賦值衅胀,比如下面兩條代碼是等價(jià)的:
element.setAttribute("id","test");
element.id = "test";
8.2 getAttribute
getAttribute()
返回元素上一個(gè)指定的屬性值。如果指定的屬性不存在酥筝,則返回null
或""
(空字符串)
語(yǔ)法
let attribute = element.getAttribute(attributeName);
attribute
是一個(gè)包含attributeName
屬性值的字符串滚躯。attributeName
是你想要獲取的屬性值的屬性名稱
例子:
<body>
<div id="div1">ABC</div>
</body>
<script>
let div1 = document.getElementById("div1");
let align = div1.getAttribute("align");
alert(align);
</script>
運(yùn)行結(jié)果:
8.3 removeAttribute
removeAttribute()
從指定的元素中刪除一個(gè)屬性
語(yǔ)法
element.removeAttribute(attrName)
attrName
是一個(gè)字符串,將要從元素中刪除的屬性名
例子:
<body>
<div id="div1" style="color:red" width="200px">ABC
</div>
</body>
<script>
let div = document.getElementById("div1")
div.removeAttribute("style");
</script>
在運(yùn)行之前div
有個(gè)style="color:red"
的屬性樱哼,在運(yùn)行之后這個(gè)屬性就被刪除了
運(yùn)行結(jié)果:
9 元素樣式型API
9.1 window.getComputedStyle
Window.getComputedStyle()
方法給出應(yīng)用活動(dòng)樣式表后的元素的所有CSS屬性的值哀九,并解析這些值可能包含的任何基本計(jì)算
假設(shè)某個(gè)元素并未設(shè)置高度而是通過(guò)其內(nèi)容將其高度撐開(kāi)剿配,這時(shí)候要獲取它的高度就要用到getComputedStyle
語(yǔ)法
var style = window.getComputedStyle(element[, pseudoElt]);
element
是要獲取的元素搅幅,pseudoElt
指定一個(gè)偽元素進(jìn)行匹配。
返回的style
是一個(gè)CSSStyleDeclaration對(duì)象呼胚。
通過(guò)style
可以訪問(wèn)到元素計(jì)算后的樣式
9.2 getBoundingClientRect
getBoundingClientRect
用來(lái)返回元素的大小以及相對(duì)于瀏覽器可視窗口的位置
語(yǔ)法
var clientRect = element.getBoundingClientRect();
clientRect
是一個(gè)DOMRect對(duì)象茄唐,包含left,top蝇更,right沪编,bottom,它是相對(duì)于可視窗口的距離年扩,滾動(dòng)位置發(fā)生改變時(shí)蚁廓,它們的值是會(huì)發(fā)生變化的。除了IE9以下瀏覽器厨幻,還包含元素的height和width等數(shù)據(jù)
9.3 直接修改元素的樣式
例子:
elem.style.color = 'red';
elem.style.setProperty('font-size', '16px');
elem.style.removeProperty('color');
9.4 動(dòng)態(tài)添加樣式規(guī)則
例子:
var style = document.createElement('style');
style.innerHTML = 'body{color:red} #top:hover{background-color: red;color: white;}';
document.head.appendChild(style););
10 總結(jié)
JavaScript中的API太多了相嵌,將這些API記住并熟練使用對(duì)JavaScript的學(xué)習(xí)是有很大的提高