1. 什么是DOM
文檔對象模型 (DOM) 是HTML和XML文檔的編程接口。它提供了對文檔的結(jié)構(gòu)化的表述,并定義了一種方式可以使從程序中對該結(jié)構(gòu)進行訪問,從而改變文檔的結(jié)構(gòu),樣式和內(nèi)容。DOM 將文檔解析為一個由節(jié)點和對象(包含屬性和方法的對象)組成的結(jié)構(gòu)集合。簡言之,它會將web頁面和腳本或程序語言連接起來。

2.DOM節(jié)點
在 HTML DOM (Document Object Model) 中 , 每一個元素都是** 節(jié)點**:
- 整個html文檔就是是一個
Document。 - 所有的HTML元素都是元素節(jié)點。
- 所有 HTML 屬性都是屬性節(jié)點。
- 文本插入到 HTML 元素是文本節(jié)點。
- 注釋是注釋節(jié)點。
3. Document 對象
- 當瀏覽器載入 HTML 文檔, 它就會成為
document對象。 -
document對象是HTML文檔的根節(jié)點與所有其他節(jié)點(元素節(jié)點,文本節(jié)點,屬性節(jié)點, 注釋節(jié)點)。 -
Document對象使我們可以從腳本中對 HTML 頁面中的所有元素進行訪問。
** 提示:**Document對象是Window對象的一部分,可通過window.document屬性對其進行訪問。
4. Document 對象屬性和方法
下表是DOM對象的全部屬性和方法列表,在列表下面,詳細地介紹了常見的原生javascript DOM操作。
| 屬性 / 方法 | 描述 |
|---|---|
document.activeElement |
返回當前獲取焦點元素 |
document.addEventListener() |
向文檔添加句柄 |
document.adoptNode(node) |
從另外一個文檔返回 adapded節(jié)點到當前文檔。 |
document.anchors |
返回對文檔中所有 Anchor 對象的引用。 |
document.applets |
返回對文檔中所有 Applet對象的引用。 |
document.baseURI |
返回文檔的絕對基礎(chǔ) URI
|
document.body |
返回文檔的body元素 |
document.close() |
關(guān)閉用 document.open()方法打開的輸出流,并顯示選定的數(shù)據(jù)。 |
document.cookie |
設(shè)置或返回與當前文檔有關(guān)的所有 cookie。 |
document.createAttribute() |
創(chuàng)建一個屬性節(jié)點 |
document.createComment() |
createComment()方法可創(chuàng)建注釋節(jié)點。 |
document.createDocumentFragment() |
創(chuàng)建空的 DocumentFragment 對象,并返回此對象。 |
document.createElement() |
創(chuàng)建元素節(jié)點。 |
document.createTextNode() |
創(chuàng)建文本節(jié)點。 |
document.doctype |
返回與文檔相關(guān)的文檔類型聲明 (DTD)。 |
document.documentElement |
返回文檔的根節(jié)點 |
document.documentMode |
返回用于通過瀏覽器渲染文檔的模式 |
document.documentURI |
設(shè)置或返回文檔的位置 |
document.domain |
返回當前文檔的域名。 |
document.domConfig |
返回normalizeDocument()被調(diào)用時所使用的配置 |
document.embeds |
返回文檔中所有嵌入的內(nèi)容(embed)集合 |
document.forms |
返回對文檔中所有 Form對象引用。 |
document. getElementsByClassName() |
返回文檔中所有指定類名的元素集合。 |
document.getElementById() |
返回對擁有指定 id 的第一個對象的引用。 |
document.getElementsByName() |
返回帶有指定名稱的對象集合。 |
document.getElementsByTagName() |
返回帶有指定標簽名的對象集合。 |
document.images |
返回對文檔中所有Image對象引用。 |
document.implementation |
返回處理該文檔的 DOMImplementation 對象。 |
document.importNode() |
把一個節(jié)點從另一個文檔復(fù)制到該文檔以便應(yīng)用。 |
document.inputEncoding |
返回用于文檔的編碼方式(在解析時)。 |
document.lastModified |
返回文檔被最后修改的日期和時間。 |
document.links |
返回對文檔中所有 Area 和Link對象引用。 |
document.normalize() |
刪除空文本節(jié)點,并連接相鄰節(jié)點 |
document.normalizeDocument() |
刪除空文本節(jié)點,并連接相鄰節(jié)點的 |
document.open() |
打開一個流,以收集來自任何 document.write() 或 document.writeln() 方法的輸出。 |
document.querySelector() |
返回文檔中匹配指定的CSS選擇器的第一元素 |
document.querySelectorAll() |
document.querySelectorAll()是 HTML5中引入的新方法,返回文檔中匹配的CSS選擇器的所有元素節(jié)點列表 |
document.readyState |
返回文檔狀態(tài) (載入中……) |
document.referrer |
返回載入當前文檔的文檔的 URL。 |
document.removeEventListener() |
移除文檔中的事件句柄(由 addEventListener()方法添加) |
document.renameNode() |
重命名元素或者屬性節(jié)點。 |
document.scripts |
返回頁面中所有腳本的集合。 |
document.strictErrorChecking |
設(shè)置或返回是否強制進行錯誤檢查。 |
document.title |
返回當前文檔的標題。 |
document.URL |
返回文檔完整的URL
|
document.write() |
向文檔寫 HTML 表達式 或 JavaScript 代碼。 |
document.writeln() |
等同于write()方法,不同的是在每個表達式之后寫一個換行符。 |
5. 常見的原生javascript DOM操作
5.1 創(chuàng)建元素
- 創(chuàng)建元素節(jié)點:
document.createElement()
使用document.createElement()可以創(chuàng)建新元素。這個方法只接受一個參數(shù),即要創(chuàng)建元素的標簽名。這個標簽名在HTML文檔中不區(qū)分大小寫,在XHTML中區(qū)分大小寫。
var div = document.createElement("div");
此時,新元素尚未被添加到文檔樹中,因此設(shè)置各種特性均不會影響瀏覽器的顯示。要添加到文檔樹,可用appendChild()、insertBefore()、replaceChild()。(稍后講到)
document.body.appendChild(div);
當把元素添加到文檔樹中后,這個元素做的任何修改都會實時地反應(yīng)到瀏覽器中。
- 創(chuàng)建文本節(jié)點 :
document.createTextNode()
使用document.createTextNode()來創(chuàng)建文本節(jié)點,這個方法接受一個參數(shù):要插入節(jié)點的文本。與設(shè)置已有文本節(jié)點的值一樣,作為參數(shù)的文本將按照HTML或XML的格式進行編碼。
document.createTextNode("121212");
可以添加多個文本節(jié)點。假如兩個文本節(jié)點是相鄰的同胞節(jié)點,那么兩個文本節(jié)點會連起來,中間不會有空格。
5.2 節(jié)點關(guān)系
(IE9以前不將換行和空格看做文本節(jié)點,其他瀏覽器會)
文本關(guān)系如下:
<div id="div1">
<div id="div2">2</div>
<div id="div3">3</div>
<div id="div4">4</div>
</div>
- 父節(jié)點:
parentNode
parentNode是指定節(jié)點的父節(jié)點。一個元素節(jié)點的父節(jié)點可能是一個元素(Element)節(jié)點,也可能是一個文檔(Document)節(jié)點,或者是個文檔碎片(DocumentFragment)節(jié)點。
每一個節(jié)點都有一個parentNode屬性。
對于下面的節(jié)點類型:Attr,Document,DocumentFragment,Entity,Notation,其parentNode屬性返回null。如果當前節(jié)點剛剛被建立,還沒有被插入到DOM樹中,則該節(jié)點的parentNode屬性也返回null。
var child2 = document.getElementById("div2");
var parent = child2.parentNode;
- 子節(jié)點:
childNodes
childNodes返回包含指定節(jié)點的子節(jié)點的** 集合**,該集合為即時更新的集合(live collection)。
即時更新就是對節(jié)點元素的任意修改都會立即反映到結(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é)點");
nodeAdd.appendChild(textAdd);
parent.appendChild(nodeAdd);
console.log(allChilds.length);// IE下是4,其他瀏覽器是8
- 兄弟節(jié)點:
nextSibling,previousSibling
nextSibling返回某節(jié)點的下一個兄弟節(jié)點,previousSibling返回某節(jié)點的上一個兄弟節(jié)點,沒有的話返回null。
注意:可能因為元素換行的原因返回的是text節(jié)點。
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
第一個或最后一個子節(jié)點:firstChild、lastChild
firstChild返回node的子節(jié)點中的第一個節(jié)點的引用,沒有返回null
lastChild返回node的子節(jié)點中的最后一個節(jié)點的引用,沒有返回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é)點元素關(guān)系
只算元素,不算文本節(jié)點。
以下三個方法用法和節(jié)點關(guān)系完全一樣,只是這三個方法只看元素節(jié)點,不管因為空格、換行造成的文本節(jié)點或者手動加上去的文本節(jié)點。
children: 返回所有** 元素子節(jié)點**(IE5+、ff3.5、opera3、chrome,但在IE8及以下會將注釋節(jié)點看成一個元素節(jié)點)
以下兩個IE9+才支持
nextElementSibling:返回元素的下一個兄弟元素節(jié)點
previousElementSibling: 返回元素的上一個兄弟元素節(jié)點
5.4 節(jié)點操作
-
appendChild()
appendChild()用于向childNodes列表的末尾添加一個節(jié)點,并且返回這個新增的節(jié)點。
如果傳入到appendChild()里的節(jié)點已經(jīng)是文檔的一部分了,那結(jié)果就是將節(jié)點從原來的位置轉(zhuǎn)移到新位置,任何一個節(jié)點不能同時出現(xiàn)在文檔中的多個位置。
var returnNode = someNode.appendChild(someNode.firstChild);
// 返回第一個節(jié)點
console.log(returnNode === someNode.firstChild); // false
console.log(returnNode === someNode.lastChild); // true
-
insetBefore()
insetBefore()可以將節(jié)點插入到某個特定的位置。這個方法接受兩個參數(shù):要插入的節(jié)點和作為參照的節(jié)點。
插入節(jié)點后,被插入的節(jié)點變成參照節(jié)點的前一個同胞節(jié)點,同時被方法返回。 如果參照節(jié)點是null,則與appendChild()執(zhí)行相同的操作。
// 插入后成為最后一個子節(jié)點
var returnNode = someNode.insetBefore(newNode, null);
console.log(returnNode === someNode.lastChild); // true
// 插入后成為第一個子節(jié)點
var returnNode = someNode.insetBefore(newNode, someNode.firstChild);
console.log(returnNode === newNode); // true
console.log(returnNode === someNode.firstChild); // true
// 插入到最后一個子節(jié)點的前面
var returnNode = someNode.insetBefore(newNode, someNode.lastChild);
console.log(returnNode === someNode.childNodes[someNode.childnodes.length - 2]) // true
- 替換節(jié)點:
replaceChild()
replaceChild()接受兩個參數(shù):要插入的節(jié)點和要被替換的節(jié)點。被替換的節(jié)點將由這個方法返回并從文檔中被移除,同時由要插入的節(jié)點占據(jù)其位置。
// 替換第一個子節(jié)點
var returnNode = someNode.replaceChild(newNode, someNode.firstChild);
使用replaceChild()后,被替換的節(jié)點的所有關(guān)系指針都會被復(fù)制到插入的節(jié)點上面。
- 刪除節(jié)點:
removeChild()
該方法移除節(jié)點,接受一個參數(shù),即要移除的節(jié)點,同時該方法返回被移除的節(jié)點。只能是一個節(jié)點,不能是一組節(jié)點。
// 移除第一個子節(jié)點
var returnNode = someNode.removeChild(newNode, someNode.firstChild);
- 克隆節(jié)點:
cloneNode(true/false)
返回調(diào)用該方法的節(jié)點的一個副本。參數(shù)表示是否采用深度克隆,如果為true,則該節(jié)點的所有后代節(jié)點也都會被克隆,如果為false,則只克隆該節(jié)點本身,文本或者換行、空格這些不會復(fù)制,因為他們都是一個textNode。
克隆一個元素節(jié)點會拷貝它所有的屬性以及屬性值,當然也就包括了屬性上綁定的事件(比如onclick="alert(1)"),但不會拷貝那些使用addEventListener()方法或者node.onclick = fn這種用JavaScript動態(tài)綁定的事件。
注意:為了防止一個文檔中出現(xiàn)兩個ID重復(fù)的元素,使用cloneNode()方法克隆的節(jié)點在需要時應(yīng)該指定另外一個與原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é)點子樹內(nèi)與之相匹配的第一個Element節(jié)點。如果沒有匹配的節(jié)點,則返回null。 -
querySelectorAll
返回一個包含節(jié)點子樹內(nèi)所有與之相匹配的Element節(jié)點列表,如果沒有相匹配的,則返回一個空節(jié)點列表。
注意:由querySelector()、querySelectorAll()返回的節(jié)點列表不是動態(tài)實時的(非live Collection)。這和其他DOM查詢方法返回動態(tài)實時節(jié)點列表不一樣。
選擇器方法接受一個或多個用逗號分隔的選擇器來確定需要被返回的元素。例如,要選擇文檔中所有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的所有元素中的第一個元素。querySelector() and querySelectorAll()里可以使用任何CSS選擇器,他們都不是live Collection:
var notLive = document.querySelectorAll("p");
console.log(notLive);
document.getElementById("div1").removeChild(document.getElementById("div2"));
console.log(notLive);
// 上面兩個輸出都是輸出 `p#div2.one`的引用,沒有因為刪除了`p`標簽而使`notLive`的結(jié)果發(fā)生變化。
-
document.getElementById()方法
返回指定 ID 的元素:
document.getElementById("demo");
-
document.getElementsByTagName()方法
返回帶有指定標簽名的對象的集合:
document.getElementsByTagName("P");
-
document.getElementsByName()方法,常用于表單(數(shù)組)
var x=document.getElementsByName("x");//x為元素name屬性值
alert(x.length);
-
getElementsByClassName()方法
當在document對象上調(diào)用此方法時,會檢索整個文檔,包括根元素。(IE9以下不支持)要匹配多個class,則className用空格分開。
getElementsByClassName("class1 class2");
5.6 屬性操作
-
setAttribute()
添加一個新屬性(attribute)到元素上,或改變元素上已經(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()返回一個布爾值,指示該元素是否包含有指定的屬性(attribute)。