1. 什么是DOM
文檔對(duì)象模型 (DOM) 是HTML和XML文檔的編程接口。它提供了對(duì)文檔的結(jié)構(gòu)化的表述炉旷,并定義了一種方式可以使從程序中對(duì)該結(jié)構(gòu)進(jìn)行訪問,從而改變文檔的結(jié)構(gòu),樣式和內(nèi)容温亲。DOM 將文檔解析為一個(gè)由節(jié)點(diǎn)和對(duì)象(包含屬性和方法的對(duì)象)組成的結(jié)構(gòu)集合藕溅。簡言之匕得,它會(huì)將web頁面和腳本或程序語言連接起來。
2.DOM節(jié)點(diǎn)
在 HTML DOM (Document Object Model) 中 , 每一個(gè)元素都是** 節(jié)點(diǎn)**:
- 整個(gè)html文檔就是是一個(gè)
Document
巾表。 - 所有的HTML元素都是元素節(jié)點(diǎn)耗跛。
- 所有 HTML 屬性都是屬性節(jié)點(diǎn)。
- 文本插入到 HTML 元素是文本節(jié)點(diǎn)攒发。
- 注釋是注釋節(jié)點(diǎn)调塌。
3. Document 對(duì)象
- 當(dāng)瀏覽器載入 HTML 文檔, 它就會(huì)成為
document
對(duì)象。 -
document
對(duì)象是HTML文檔的根節(jié)點(diǎn)與所有其他節(jié)點(diǎn)(元素節(jié)點(diǎn)惠猿,文本節(jié)點(diǎn)羔砾,屬性節(jié)點(diǎn), 注釋節(jié)點(diǎn))。 -
Document
對(duì)象使我們可以從腳本中對(duì) HTML 頁面中的所有元素進(jìn)行訪問偶妖。
** 提示:**Document
對(duì)象是Window
對(duì)象的一部分姜凄,可通過window.document
屬性對(duì)其進(jìn)行訪問。
4. Document 對(duì)象屬性和方法
下表是DOM對(duì)象的全部屬性和方法列表趾访,在列表下面态秧,詳細(xì)地介紹了常見的原生javascript DOM操作。
屬性 / 方法 | 描述 |
---|---|
document.activeElement |
返回當(dāng)前獲取焦點(diǎn)元素 |
document.addEventListener() |
向文檔添加句柄 |
document.adoptNode(node) |
從另外一個(gè)文檔返回 adapded 節(jié)點(diǎn)到當(dāng)前文檔扼鞋。 |
document.anchors |
返回對(duì)文檔中所有 Anchor 對(duì)象的引用申鱼。 |
document.applets |
返回對(duì)文檔中所有 Applet 對(duì)象的引用。 |
document.baseURI |
返回文檔的絕對(duì)基礎(chǔ) URI
|
document.body |
返回文檔的body 元素 |
document.close() |
關(guān)閉用 document.open() 方法打開的輸出流云头,并顯示選定的數(shù)據(jù)捐友。 |
document.cookie |
設(shè)置或返回與當(dāng)前文檔有關(guān)的所有 cookie 。 |
document.createAttribute() |
創(chuàng)建一個(gè)屬性節(jié)點(diǎn) |
document.createComment() |
createComment() 方法可創(chuàng)建注釋節(jié)點(diǎn)溃槐。 |
document.createDocumentFragment() |
創(chuàng)建空的 DocumentFragment 對(duì)象匣砖,并返回此對(duì)象。 |
document.createElement() |
創(chuàng)建元素節(jié)點(diǎn)昏滴。 |
document.createTextNode() |
創(chuàng)建文本節(jié)點(diǎn)猴鲫。 |
document.doctype |
返回與文檔相關(guān)的文檔類型聲明 (DTD )。 |
document.documentElement |
返回文檔的根節(jié)點(diǎn) |
document.documentMode |
返回用于通過瀏覽器渲染文檔的模式 |
document.documentURI |
設(shè)置或返回文檔的位置 |
document.domain |
返回當(dāng)前文檔的域名谣殊。 |
document.domConfig |
返回normalizeDocument() 被調(diào)用時(shí)所使用的配置 |
document.embeds |
返回文檔中所有嵌入的內(nèi)容(embed )集合 |
document.forms |
返回對(duì)文檔中所有 Form 對(duì)象引用拂共。 |
document. getElementsByClassName() |
返回文檔中所有指定類名的元素集合。 |
document.getElementById() |
返回對(duì)擁有指定 id 的第一個(gè)對(duì)象的引用蟹倾。 |
document.getElementsByName() |
返回帶有指定名稱的對(duì)象集合匣缘。 |
document.getElementsByTagName() |
返回帶有指定標(biāo)簽名的對(duì)象集合猖闪。 |
document.images |
返回對(duì)文檔中所有Image 對(duì)象引用。 |
document.implementation |
返回處理該文檔的 DOMImplementation 對(duì)象肌厨。 |
document.importNode() |
把一個(gè)節(jié)點(diǎn)從另一個(gè)文檔復(fù)制到該文檔以便應(yīng)用培慌。 |
document.inputEncoding |
返回用于文檔的編碼方式(在解析時(shí))。 |
document.lastModified |
返回文檔被最后修改的日期和時(shí)間柑爸。 |
document.links |
返回對(duì)文檔中所有 Area 和Link 對(duì)象引用吵护。 |
document.normalize() |
刪除空文本節(jié)點(diǎn),并連接相鄰節(jié)點(diǎn) |
document.normalizeDocument() |
刪除空文本節(jié)點(diǎn)表鳍,并連接相鄰節(jié)點(diǎn)的 |
document.open() |
打開一個(gè)流馅而,以收集來自任何 document.write() 或 document.writeln() 方法的輸出。 |
document.querySelector() |
返回文檔中匹配指定的CSS選擇器的第一元素 |
document.querySelectorAll() |
document.querySelectorAll() 是 HTML5中引入的新方法譬圣,返回文檔中匹配的CSS 選擇器的所有元素節(jié)點(diǎn)列表 |
document.readyState |
返回文檔狀態(tài) (載入中……) |
document.referrer |
返回載入當(dāng)前文檔的文檔的 URL 瓮恭。 |
document.removeEventListener() |
移除文檔中的事件句柄(由 addEventListener() 方法添加) |
document.renameNode() |
重命名元素或者屬性節(jié)點(diǎn)。 |
document.scripts |
返回頁面中所有腳本的集合厘熟。 |
document.strictErrorChecking |
設(shè)置或返回是否強(qiáng)制進(jìn)行錯(cuò)誤檢查屯蹦。 |
document.title |
返回當(dāng)前文檔的標(biāo)題。 |
document.URL |
返回文檔完整的URL
|
document.write() |
向文檔寫 HTML 表達(dá)式 或 JavaScript 代碼绳姨。 |
document.writeln() |
等同于write() 方法登澜,不同的是在每個(gè)表達(dá)式之后寫一個(gè)換行符。 |
5. 常見的原生javascript DOM操作
5.1 創(chuàng)建元素
- 創(chuàng)建元素節(jié)點(diǎn):
document.createElement()
使用document.createElement()
可以創(chuàng)建新元素飘庄。這個(gè)方法只接受一個(gè)參數(shù)脑蠕,即要?jiǎng)?chuàng)建元素的標(biāo)簽名。這個(gè)標(biāo)簽名在HTML
文檔中不區(qū)分大小寫跪削,在XHTML
中區(qū)分大小寫谴仙。
var div = document.createElement("div");
此時(shí),新元素尚未被添加到文檔樹中切揭,因此設(shè)置各種特性均不會(huì)影響瀏覽器的顯示狞甚。要添加到文檔樹锁摔,可用appendChild()
廓旬、insertBefore()
、replaceChild()
谐腰。(稍后講到)
document.body.appendChild(div);
當(dāng)把元素添加到文檔樹中后,這個(gè)元素做的任何修改都會(huì)實(shí)時(shí)地反應(yīng)到瀏覽器中。
- 創(chuàng)建文本節(jié)點(diǎn) :
document.createTextNode()
使用document.createTextNode()
來創(chuàng)建文本節(jié)點(diǎn)十饥,這個(gè)方法接受一個(gè)參數(shù):要插入節(jié)點(diǎn)的文本瑟枫。與設(shè)置已有文本節(jié)點(diǎn)的值一樣,作為參數(shù)的文本將按照HTML
或XML
的格式進(jìn)行編碼砸西。
document.createTextNode("121212");
可以添加多個(gè)文本節(jié)點(diǎn)叶眉。假如兩個(gè)文本節(jié)點(diǎn)是相鄰的同胞節(jié)點(diǎn)址儒,那么兩個(gè)文本節(jié)點(diǎn)會(huì)連起來,中間不會(huì)有空格衅疙。
5.2 節(jié)點(diǎn)關(guān)系
(IE9
以前不將換行和空格看做文本節(jié)點(diǎn)莲趣,其他瀏覽器會(huì))
文本關(guān)系如下:
<div id="div1">
<div id="div2">2</div>
<div id="div3">3</div>
<div id="div4">4</div>
</div>
- 父節(jié)點(diǎn):
parentNode
parentNode
是指定節(jié)點(diǎn)的父節(jié)點(diǎn)。一個(gè)元素節(jié)點(diǎn)的父節(jié)點(diǎn)可能是一個(gè)元素(Element
)節(jié)點(diǎn)饱溢,也可能是一個(gè)文檔(Document
)節(jié)點(diǎn)喧伞,或者是個(gè)文檔碎片(DocumentFragment
)節(jié)點(diǎn)。
每一個(gè)節(jié)點(diǎn)都有一個(gè)parentNode
屬性绩郎。
對(duì)于下面的節(jié)點(diǎn)類型:Attr
,Document
潘鲫,DocumentFragment
,Entity
,Notation
,其parentNode
屬性返回null
肋杖。如果當(dāng)前節(jié)點(diǎn)剛剛被建立,還沒有被插入到DOM
樹中溉仑,則該節(jié)點(diǎn)的parentNode
屬性也返回null
。
var child2 = document.getElementById("div2");
var parent = child2.parentNode;
- 子節(jié)點(diǎn):
childNodes
childNodes
返回包含指定節(jié)點(diǎn)的子節(jié)點(diǎn)的** 集合**状植,該集合為即時(shí)更新的集合(live collection
)彼念。
即時(shí)更新就是對(duì)節(jié)點(diǎn)元素的任意修改都會(huì)立即反映到結(jié)果里。
var child2 = document.getElementById("div2");
var parent = child2.parentNode;
var allChilds = parent.childNodes;
console.log(allChilds.length) // IE下是3浅萧,其他瀏覽器是7
var nodeAdd = document.createElement("div");
var textAdd = document.createTextNode("這是添加的文本節(jié)點(diǎn)");
nodeAdd.appendChild(textAdd);
parent.appendChild(nodeAdd);
console.log(allChilds.length);// IE下是4逐沙,其他瀏覽器是8
- 兄弟節(jié)點(diǎn):
nextSibling
,previousSibling
nextSibling
返回某節(jié)點(diǎn)的下一個(gè)兄弟節(jié)點(diǎn)洼畅,previousSibling
返回某節(jié)點(diǎn)的上一個(gè)兄弟節(jié)點(diǎn)吩案,沒有的話返回null
。
注意:可能因?yàn)樵負(fù)Q行的原因返回的是text
節(jié)點(diǎn)帝簇。
var child3 = document.getElementById("div3");
var next = child3.nextSibling;
var previous = child3.previousSibling;
console.log(next); // IE下返回div4徘郭,其他返回text
console.log(previous) // IE下返回div2,其他返回text
第一個(gè)或最后一個(gè)子節(jié)點(diǎn):firstChild
丧肴、lastChild
firstChild
返回node
的子節(jié)點(diǎn)中的第一個(gè)節(jié)點(diǎn)的引用残揉,沒有返回null
lastChild
返回node
的子節(jié)點(diǎn)中的最后一個(gè)節(jié)點(diǎn)的引用,沒有返回null
var child3 = document.getElementById("div3");
var parent = child3.parentNode;
var first = parent.firstChild; // IE是div2芋浮,其他是text
var last = parent.lastChild; // IE是div4抱环,其他是text
5.3 節(jié)點(diǎn)元素關(guān)系
只算元素,不算文本節(jié)點(diǎn)纸巷。
以下三個(gè)方法用法和節(jié)點(diǎn)關(guān)系完全一樣镇草,只是這三個(gè)方法只看元素節(jié)點(diǎn),不管因?yàn)榭崭窳鲋肌Q行造成的文本節(jié)點(diǎn)或者手動(dòng)加上去的文本節(jié)點(diǎn)梯啤。
children
: 返回所有** 元素子節(jié)點(diǎn)**(IE5+、ff3.5存哲、opera3因宇、chrome七婴,但在IE8及以下會(huì)將注釋節(jié)點(diǎn)看成一個(gè)元素節(jié)點(diǎn))
以下兩個(gè)IE9+才支持
nextElementSibling
:返回元素的下一個(gè)兄弟元素節(jié)點(diǎn)
previousElementSibling
: 返回元素的上一個(gè)兄弟元素節(jié)點(diǎn)
5.4 節(jié)點(diǎn)操作
-
appendChild()
appendChild()
用于向childNodes
列表的末尾添加一個(gè)節(jié)點(diǎn),并且返回這個(gè)新增的節(jié)點(diǎn)察滑。
如果傳入到appendChild()
里的節(jié)點(diǎn)已經(jīng)是文檔的一部分了本姥,那結(jié)果就是將節(jié)點(diǎn)從原來的位置轉(zhuǎn)移到新位置,任何一個(gè)節(jié)點(diǎn)不能同時(shí)出現(xiàn)在文檔中的多個(gè)位置杭棵。
var returnNode = someNode.appendChild(someNode.firstChild);
// 返回第一個(gè)節(jié)點(diǎn)
console.log(returnNode === someNode.firstChild); // false
console.log(returnNode === someNode.lastChild); // true
-
insetBefore()
insetBefore()
可以將節(jié)點(diǎn)插入到某個(gè)特定的位置婚惫。這個(gè)方法接受兩個(gè)參數(shù):要插入的節(jié)點(diǎn)和作為參照的節(jié)點(diǎn)。
插入節(jié)點(diǎn)后魂爪,被插入的節(jié)點(diǎn)變成參照節(jié)點(diǎn)的前一個(gè)同胞節(jié)點(diǎn)先舷,同時(shí)被方法返回。 如果參照節(jié)點(diǎn)是null
滓侍,則與appendChild()
執(zhí)行相同的操作蒋川。
// 插入后成為最后一個(gè)子節(jié)點(diǎn)
var returnNode = someNode.insetBefore(newNode, null);
console.log(returnNode === someNode.lastChild); // true
// 插入后成為第一個(gè)子節(jié)點(diǎn)
var returnNode = someNode.insetBefore(newNode, someNode.firstChild);
console.log(returnNode === newNode); // true
console.log(returnNode === someNode.firstChild); // true
// 插入到最后一個(gè)子節(jié)點(diǎn)的前面
var returnNode = someNode.insetBefore(newNode, someNode.lastChild);
console.log(returnNode === someNode.childNodes[someNode.childnodes.length - 2]) // true
- 替換節(jié)點(diǎn):
replaceChild()
replaceChild()
接受兩個(gè)參數(shù):要插入的節(jié)點(diǎn)和要被替換的節(jié)點(diǎn)。被替換的節(jié)點(diǎn)將由這個(gè)方法返回并從文檔中被移除撩笆,同時(shí)由要插入的節(jié)點(diǎn)占據(jù)其位置捺球。
// 替換第一個(gè)子節(jié)點(diǎn)
var returnNode = someNode.replaceChild(newNode, someNode.firstChild);
使用replaceChild()
后,被替換的節(jié)點(diǎn)的所有關(guān)系指針都會(huì)被復(fù)制到插入的節(jié)點(diǎn)上面夕冲。
- 刪除節(jié)點(diǎn):
removeChild()
該方法移除節(jié)點(diǎn)氮兵,接受一個(gè)參數(shù),即要移除的節(jié)點(diǎn)歹鱼,同時(shí)該方法返回被移除的節(jié)點(diǎn)泣栈。只能是一個(gè)節(jié)點(diǎn),不能是一組節(jié)點(diǎn)弥姻。
// 移除第一個(gè)子節(jié)點(diǎn)
var returnNode = someNode.removeChild(newNode, someNode.firstChild);
- 克隆節(jié)點(diǎn):
cloneNode(true/false)
返回調(diào)用該方法的節(jié)點(diǎn)的一個(gè)副本南片。參數(shù)表示是否采用深度克隆,如果為true
庭敦,則該節(jié)點(diǎn)的所有后代節(jié)點(diǎn)也都會(huì)被克隆,如果為false
疼进,則只克隆該節(jié)點(diǎn)本身,文本或者換行秧廉、空格這些不會(huì)復(fù)制伞广,因?yàn)樗麄兌际且粋€(gè)textNode
。
克隆一個(gè)元素節(jié)點(diǎn)會(huì)拷貝它所有的屬性以及屬性值,當(dāng)然也就包括了屬性上綁定的事件(比如onclick="alert(1)")
定血,但不會(huì)拷貝那些使用addEventListener()
方法或者node.onclick = fn
這種用JavaScript動(dòng)態(tài)綁定的事件赔癌。
注意:為了防止一個(gè)文檔中出現(xiàn)兩個(gè)ID
重復(fù)的元素,使用cloneNode()方法克隆的節(jié)點(diǎn)在需要時(shí)應(yīng)該指定另外一個(gè)與原ID
值不同的ID
var div1 = document.getElementById("div1");
var cloneHtml = div1.cloneNode(true);
document.body.appendChild(cloneHtml);
5.5 元素選擇
HTML代碼示例:
<div id="div1">
<p id="div2" class="one" name="nameone">2</p>
<div id="div3">3</div>
<div id="div4" name="div2">4</div>
</div>
-
querySelector
返回節(jié)點(diǎn)子樹內(nèi)與之相匹配的第一個(gè)Element
節(jié)點(diǎn)。如果沒有匹配的節(jié)點(diǎn)澜沟,則返回null
。 -
querySelectorAll
返回一個(gè)包含節(jié)點(diǎn)子樹內(nèi)所有與之相匹配的Element
節(jié)點(diǎn)列表峡谊,如果沒有相匹配的茫虽,則返回一個(gè)空節(jié)點(diǎn)列表刊苍。
注意:由querySelector()
、querySelectorAll()
返回的節(jié)點(diǎn)列表不是動(dòng)態(tài)實(shí)時(shí)的(非live Collection
)濒析。這和其他DOM查詢方法返回動(dòng)態(tài)實(shí)時(shí)節(jié)點(diǎn)列表不一樣正什。
選擇器方法接受一個(gè)或多個(gè)用逗號(hào)分隔的選擇器來確定需要被返回的元素。例如号杏,要選擇文檔中所有CSS的類(class
)是warning
或者note
的段落(p
)元素,可以這樣寫:
var special = document.querySelectorAll( "p.warning, p.note" );
也可以通過ID來查詢婴氮,例如:
var el = document.querySelector( "#main, #basic, #exclamation" );
執(zhí)行上面的代碼后,el
就包含了文檔中元素的ID是main
盾致,basic
或exclamation
的所有元素中的第一個(gè)元素主经。querySelector() and querySelectorAll()
里可以使用任何CSS選擇器,他們都不是live Collection
:
var notLive = document.querySelectorAll("p");
console.log(notLive);
document.getElementById("div1").removeChild(document.getElementById("div2"));
console.log(notLive);
// 上面兩個(gè)輸出都是輸出 `p#div2.one`的引用庭惜,沒有因?yàn)閯h除了`p`標(biāo)簽而使`notLive`的結(jié)果發(fā)生變化罩驻。
-
document.getElementById()
方法
返回指定 ID 的元素:
document.getElementById("demo");
-
document.getElementsByTagName()
方法
返回帶有指定標(biāo)簽名的對(duì)象的集合:
document.getElementsByTagName("P");
-
document.getElementsByName()
方法,常用于表單(數(shù)組)
var x=document.getElementsByName("x");//x為元素name屬性值
alert(x.length);
-
getElementsByClassName()
方法
當(dāng)在document
對(duì)象上調(diào)用此方法時(shí)护赊,會(huì)檢索整個(gè)文檔惠遏,包括根元素。(IE9
以下不支持)要匹配多個(gè)class
骏啰,則className
用空格分開节吮。
getElementsByClassName("class1 class2");
5.6 屬性操作
-
setAttribute()
添加一個(gè)新屬性(attribute
)到元素上,或改變?cè)厣弦呀?jīng)存在的屬性的值判耕。
如果指定的屬性已經(jīng)存在课锌,則其值變?yōu)閭鬟f的值。如果不存在祈秕,則創(chuàng)建指定的屬性渺贤。也可指定為null
。如果設(shè)置為null
请毛,最好使用removeAttribute()
志鞍。
var div2 = document.getElementById("div2");
div2.setAttribute("class", "new_class");
div2.setAttribute("id", "new_id");
-
removeAttribute()
該方法用于移除元素的屬性。
var div2 = document.getElementById("div2");
div2.removeAttribute("class");
-
getAttribute()
該方法返回元素上指定屬性(attribute
)的值方仿。如果指定的屬性不存在固棚,則返回null
或""
(空字符串)。
var div2 = document.getElementById("div2");
var attr = div2.getAttribute("class");
console.log(attr);
-
hasAttribute()
hasAttribute()
返回一個(gè)布爾值仙蚜,指示該元素是否包含有指定的屬性(attribute
)此洲。