##1.DOM 節點的常用屬性(所有節點都支援)##
-
nodeType:元素 1,屬性 2,文本 3
-
nodeName:元素標籤名的大寫形式
-
nodeValue:元素節點為 null,文本節點為文本內容,屬性節點為屬性值
-
關係屬性:parentNode,childNodes,nextSibling,previousSibling,firstChild,lastChild
-
ownerDocument:文檔節點(document 物件)
##2.操作 DOM 節點(增/刪/改)##
-
appendChild(node);給當前節點的 childNodes 列表末尾添加一個節點。若 node 已存在,則把 node 移動到當前節點下
-
insertBefore(node, targetNode);在 targetNode 前插入 node
-
replaceChild(node, targetNode);用 node 替換 targetNode,注意:替換之後 targetNode並沒有被銷毀,只是變成了遊離在 DOM 樹外的文檔碎片
-
removeChild(node);移除 node,注意:移除之後 node也沒有被銷毀,該方法返回 node 的引用
-
cloneNode(true/false);複製一個與當前節點完全相同的節點,若 true 則深複製,否則淺複製,IE 會複製相關事件處理器,其它瀏覽器不會
-
normalize();用來刪掉空文本節點,合併相鄰文本節點
##3.document 物件相關##
-
document.documentElement;指向元素
-
document.body;指向元素
-
document.title;指向元素,直接賦值可以修改文檔標題
-
document.URL;獲取完整 URL
document.domain;獲取域名,可以直接賦值設置域名,當頁面中多個 frame 需要通信時必須修改該屬性,以解除跨域安全限制
document.referrer;獲取上一個頁面的 url,可能是空串
-
查找元素
-
document.getElementById(str);
-
document.getElementsByTagName(str);返回集合,用方括號語法訪問,方括號內可以是字符串表示按 name 屬性值取元素(str 可以是*表示取所有 DOM 元素)
-
document.getElementsByName(str);多用於單選按鈕組
-
P.S.前兩個適用於所有 XML 文檔的 DOM 操作,最後一個只適用於 HTML 文檔。至於 HTML5 支援的 document.querySelector(str) 以及 document.getElementsByClassName(str) 不在此討論,上面列出的 3 種方式都是全瀏覽器相容的
-
document.write(str);文檔寫入,文檔加載過程中直接調用則在指定位置輸出內容,若放在 load 事件處理器中則重寫整個頁面
-
document.createTextNode(text);創建文本節點。document.createElement(tagName);創建元素
##4.元素節點相關##
-
元素節點的屬性:id、title(類似於 ToolTip)、className,都是可讀/寫的(寫原生 js 代碼時這 3 個屬性很常用,尤其是className,很方便)
-
elem.getAttribute(attr);獲取 attr 屬性的值,也可以取得自定義屬性,但 HTML5 中自定義屬性應該加上"data-"前綴(當然,不加也沒關係,只是規範要求),用 elem.dataset.attr 獲取
elem.setAttribute(attr, value);設置屬性值,只用來設置自定義屬性,因為自定義屬性無法直接設置
elem.removeAttribute(attr);刪除屬性和值([IE6-]不支援)
P.S.一般直接訪問屬性,例如 elem.id, elem.style 等等,get/setAttribute 方式並不常用(只用來讀/寫自定義屬性),因為用函數方式訪問 style 和 onclick 或其它事件屬性返回字符串,而直接訪問可以返回可操作物件(比如函數引用),所以一般都直接訪問元素屬性
-
attributes 屬性:elem.attributes['id'].nodeValue = value;也可以通過這種方式來訪問屬性,但更多的時候用 attributes 屬性來遍歷元素屬性
-
遍歷元素的節點時應該添加 nodeType 檢測,因為有些瀏覽器會把標籤間的空白字符也當作節點(Unicode 簽名 BOM)
##5.文本節點##
node.nodeValue 或者 node.data 都可以訪問文本內容
##6.DOM 性能優化##
- 盡量減少訪問 NodeList 的次數
NodeList、NamedNodeMap、HTMLCollection 都是實時更新的,document.getElementByxxx 的返回值就是該類型的。應該盡量減少訪問 NodeList 的次數,因為訪問時需要檢查 DOM 樹,存在不小的性能損耗。可以把 NodeList 物件的引用保存起來,例如不要出現下面的代碼:
for(var i = 0;i < 100;i++){
document.getElementsByTagName('li')[i].className = 'disabled';
}
這樣做簡直太傷了,更好的做法是:
var lis = document.getElementsByTagName('li');
for(var i = 0;i < 100;i++){
lis[i].className = 'disabled';
}
常見的 HTMLCollection 物件有:document.forms、document.images、document.links、document.anchors
- 使用 DocumentFragment 避免多次「現場更新」
DocumentFragment 是一種比較冷门但非常有用的節點,在性能優化中尤其重要,需要插入大量 DOM 節點時,我們有兩個選擇:要麼一個一個往 DOM 樹上插,要麼先插到文檔碎片上,再把文檔碎片插入 DOM 樹。第一種方式需要更新 n 次 DOM 樹,而第二種方式只需要更新 1 次,例如:
//創建文檔碎片
var frag = document.createDocumentFragment();
//插入節點
var node = null, text = null;
for(var i = 0;i < 10;i++){
node = document.createElement('p');
text = document.createTextNode('段落' + i);
node.appendChild(text);
frag.appendChild(node);
}
//把攜帶著節點的文檔碎片插入 DOM 樹
document.body.appendChild(frag);
文檔碎片在 DOM 樹中是不存在的,把碎片插入 DOM 樹實際上是插入了它攜帶的節點,文檔碎片是一個看不見的容器。當然也可以創建一個 div 作為容器,和創建文檔碎片道理一樣,只要能避免 n 次現場更新就好,因為 DOM 樹上任何一個節點更新時瀏覽器都會重新渲染頁面,這意味著大量的樣式數值計算
- getElementByxxx 的性能差異
Id 查詢是最快的,TagName 次之,ClassName 最慢。當然,一般情況下這些差異是可以忽略的,但移動端頁面應該充分考慮,畢竟移動端沒有 PC 這麼好的條件。此外,把頻繁使用的元素的引用保存一份可以減少不必要的 DOM 查找,從而提升性能。
##7.動態創建 img/script/link 元素##
鑒於這部分內容和一般的 DOM 操作不同,和事件的關聯比較多,所以放在[JS 學習筆記 6_事件](http://ayqy.net/blog/js 學習筆記 6_事件/)中詳述
暫無評論,快來發表你的看法吧