原生 JavaScript 的 DOM 操作彙總
經常有人講在 IDE 中寫 C#、Java 會越來越手殘,那麼經常用 jQuery 也會讓我們忘記 JavaScript 是如何操作 DOM 的。 JavaScript的DOM操作也是面試中的常見問題,尤其是當你需要回答jQuery的效能問題時,便需要再次回到JavaScript DOM API。 本文便總結一下常見的 JavaScript DOM 操作方法,關於 JavaScript DOM 事件可以參考另一篇文章:DOM Level 2 Event 與 jQuery 原始碼:捕獲與冒泡
什麼是 DOM?
外行看來前端工程師的工作就是改頁面(HTML、CSS),寫指令碼(JavaScript)。當你意識到你不是在改HTML而是在操作DOM時,你就升級了! 那麼什麼是DOM?
MDN:文件物件模型 (DOM)是HTML和XML文件的程式設計介面。它提供了對文件的結構化的表述,並定義了一種方式可以使從程式中對該結構進行訪問,從而改變文件的結構,樣式和內容。DOM 將文件解析為一個由節點和物件(包含屬性和方法的物件)組成的結構集合。簡言之,它會將web頁面和指令碼或程式語言連線起來。
說白了 DOM 就是瀏覽器為 JavaScript 提供的一系列介面(通過window.documnet
提供的),通過這些介面我們可以操作web頁面。但DOM並不是程式語言,它是文件物件的模型,該模型是獨立於程式語言的。比如我們在Python中也可以操作DOM:
import xml.dom.minidom as m
doc = m.parse("C:\\Projects\\Py\\chap1.xml");
doc.nodeName # DOM property of document object;
p_list = doc.getElementsByTagName("para");
所以Web前端常講的DOM API (web 或 XML 頁面) = DOM + JS (指令碼語言)
DOM 建立
DOM節點(Node)通常對應於一個標籤,一個文字,或者一個HTML屬性。DOM節點有一個nodeType
屬性用來表示當前元素的型別,它是一個整數:
- Element,元素
- Attribute,屬性
- Text,文字
DOM節點建立最常用的便是document.createElement和document.createTextNode
方法:
var el1 = document.createElement('div');
var el2 = document.createElement('input');
var node = document.createTextNode('hello world!');
DOM 查詢
元素查詢的API返回的的結果是DOM節點或者DOM節點的列表。document
提供了兩種Query方法:
// 返回當前文件中第一個類名為 "myclass" 的元素
var el = document.querySelector(".myclass");
// 返回一個文件中所有的class為"note"或者 "alert"的div元素
var els = document.querySelectorAll("div.note, div.alert");
// 獲取元素
var el = document.getElementById('xxx');
var els = document.getElementsByClassName('highlight');
var els = document.getElementsByTagName('td');
Element也提供了很多相對於元素的DOM導航方法:
// 獲取父元素、父節點
var parent = ele.parentElement;
var parent = ele.parentNode;
// 獲取子節點,子節點可以是任何一種節點,可以通過nodeType來判斷
var nodes = ele.children;
// 查詢子元素
var els = ele.getElementsByTagName('td');
var els = ele.getElementsByClassName('highlight');
// 當前元素的第一個/最後一個子元素節點
var el = ele.firstElementChild;
var el = ele.lastElementChild;
// 下一個/上一個兄弟元素節點
var el = ele.nextElementSibling;
var el = ele.previousElementSibling;
DOM 更改
// 新增、刪除子元素
ele.appendChild(el);
ele.removeChild(el);
// 替換子元素
ele.replaceChild(el1, el2);
// 插入子元素
parentElement.insertBefore(newElement, referenceElement);
屬性操作
// 獲取一個{name, value}的陣列
var attrs = el.attributes;
// 獲取、設定屬性
var c = el.getAttribute('class');
el.setAttribute('class', 'highlight');
// 判斷、移除屬性
el.hasAttribute('class');
el.removeAttribute('class');
// 是否有屬性設定
el.hasAttributes();
常見的面試問題
innerHTML 與 outerHTML 的區別?
DOM 元素的innerHTML
,outerHTML
,innerText
,outerText
屬性的區別也經常被面試官問到, 比如對於這樣一個HTML元素:<div>content<br/></div>
。
innerHTML
:內部HTML,content<br/>
;outerHTML
:外部HTML,<div>content<br/></div>
;innerText
:內部文字,content
;outerText
:內部文字,content
;
上述四個屬性不僅可以讀取,還可以賦值。outerText
和innerText
的區別在於outerText
賦值時會把標籤一起賦值掉,另外xxText
賦值時HTML特殊字元會被轉義。 下圖來源於:http://walsh.iteye.com/blog/261966
jQuery的html()與innerHTML的區別?
jQuery的.html()
會呼叫.innerHTML
來操作,但是會捕獲異常,然後用.empty()
,.append()
重新操作。 這是因為IE8中有些元素的.innerHTML
是隻讀的。見:http://stackoverflow.com/questions/3563107/jquery-html-vs-innerhtml
本文采用知識共享署名 4.0 國際許可協議(CC-BY 4.0)進行許可,轉載註明來源即可:https://harttle.land/2015/10/01/javascript-dom-api.html。學識粗淺寫作倉促,如有錯誤辛苦評論或郵件指出。