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