原生JS的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特殊字元會被轉義。
jQuery的html()與innerHTML的區別?
jQuery的.html()
會呼叫.innerHTML
來操作,但同時也會catch
異常,然後用.empty()
, .append()
來重新操作。
這是因為IE8中有些元素的.innerHTML
是隻讀的。見:http://stackoverflow.com/questions/3563107/jquery-html-vs-innerhtml