HTML
- innerHTML:內部HTML,content<br/>;
- outerHTML:外部HTML,<div>content<br/></div>;
- innerText:不會返回隱藏元素的文本,受 CSS 樣式的影響,它會觸發重排(reflow);IE11及以下,不僅會移除當前元素的子節點,而且還會永久性地破壞所有后代文本節點
- textContent,會獲取所有元素的內容,包括 css內容;對比innerText,不會引起重排;兼容性: IE9開始支持
- outerText:outerText 賦值時會把整個標簽一起賦值掉;非標准屬性,不要在生產環境中使用!
jQuery的html()會調用innerHTML()來操作,但同時也會 catch 異常,然后用.empty(),.append()來重新操作.這是因為IE8中有些元素的.innerHTML是只讀的
Node 節點
Node是一個接口,許多DOM類型從這個接口繼承,常用如元素節點,文本節點,屬性節點.
每個node對象均有nodeValue,nodeType屬性:
-
nodeValue- 元素節點值是 undefined 或 null
- 文本節點值是 文本本身
- 屬性節點值是 屬性值,使用 getAttribute()
-
常用
nodeType- 1 Element 元素節點
- 2 Attr 屬性節點
- 3 Text 文本節點
- 4 CDATASection
- 9 Document DOM 樹的根節點
- 11 DocumentFragment
可以用在遍歷DOM樹時使用節點類型過濾
var allChildren = document.getElementById('inhere');
for(var i = 0; i < allChildren.length; i++) {
if(allChildren[i].nodeType == 1 && allChildren[i].hasAttribute('someattr')) {
// …
break;
}
}
NodeList是一個節點的集合,具有以下特征:
-
實時性
由 Node.childNodes 和 document.querySelectorAll 返回,大多數情況下是一個實時的集合,當文檔節點變化時,NodeList對象也會變化.因此當使用完該對象后,避免保留節點引用是好的編程習慣.在遍歷節點集合的時候應避免對DOM進行操作影響遍歷過程;需要注意的是例外情況:document.querySelectorAll 返回的是靜態集合. -
節點集合與數組
NodeList 繼承自 NodeList.prototype,而數組繼承自Array.prototype,因此要想使用數組方法有很多方法:- 使用原型鏈把Array.prototype 上的方法添加到 NodeList.prototype, 但是擴展 DOM對象的原型鏈是很危險
- 數組原型方法使用 call將 NodeList 作為this參數傳遞給原生方法,不保證所有瀏覽器均兼容
- 將 Nodelist 轉化為數組:Array.prototype.slice.call(NodeList),可以簡單使用[].slice.call(NodeList) 兼容性:IE9+
-
HTMLCollection
- 很明顯
HTMLCollection只是元素節點的集合,不同的是元素節點集合是實時的,而Nodelist不總是實時的 Node.childNodes返回的是NodeList,而node.children返回的是HTMLCollection
- 很明顯
常用API
節點操作
- element.hasChildNodes 是否擁有子節點
- element.children 返回節點元素集合
- element.childNodes 返回子節點集合
- element.parentNode 返回父節點
- element.cloneNode(deep)克隆節點,包括所有屬性及屬性值(包括 onclick,但不包括 addEventListener,onclick=fn這種動態綁定)
屬性和樣式操作
- element.getAttributeNode() 獲取指定屬性的節點
- element.setAttribute() 為節點設置屬性,若屬性不存在多數情況下返回null,某些返回空字符串,所以判斷是否有指定屬性,應使用 hasAttribute
- element.hasAttribute() 判斷是否有指定屬性
- element.style 獲取或者設置樣式
- element.className 獲取或者設置屬性
創建,刪除和替換節點
- document.createElement() 創建元素節點
- document.createTextNode() 創建一個文本節點
- document.createDocumentFragment() 創建DocumentFragment節點
- element.appendChild() 向節點子節點列表的末尾添加新的子節點
- element.removeChild() 刪除節點;刪除自己時,需要用 parentNode.removeChild()
- document.replaceChild() 替換元素節點
- document.replaceData() 替換文本節點() 不如直接操作nodeValue
獲取節點
- document.getElementById() 根據id返回一個 Element 對象,沒有返回 null
- document.getElementsByClassName
- document.getElementsByTagName(name) 返回一個 HTMLCollection;在 WebKit 內核的瀏覽器中返回一個 NodeList
- document.getElementsByName(name) name:是元素的 name 屬性的值;返回一個 NodeList 集合
- document.querySelector
- 使用深度優先先序遍歷文檔的節點
- 如果沒有找到匹配元素,則返回 null
- 返回第一個匹配的節點
- document.querySellectorAll 返回一個 NodeList,並且是靜態集合
高效遍歷 DOM
- 使用
nodeType過濾 - 使用XPath
- 遍歷時盡量不對 DOM 操作
var allPara = document.getElementsByTagName('p');
for(var i = 0; i < allPara.length; i++) {
allPara[i].appendChild(document.createTextNode(i));
}
→
var allPara = document.getElementsByTagName('p');
var collectTemp = [];
for(var i = 0; i < allPara.length; i++) {
collectTemp[collectTemp.length] = allPara[i];
}
for(i = 0; i < collectTemp.length; i++) {
collectTemp[i].appendChild(document.createTextNode(i));
}
collectTemp = null;
Repaint and reflow
插入大量內容避免重繪和回流
- createDocumentFragment
var docFragm = document.createDocumentFragment();
var elem, contents;
for(var i = 0; i < textlist.length; i++) {
elem = document.createElement('p');
contents = document.createTextNode(textlist[i]);
elem.appendChild(contents);
docFragm.appendChild(elem);
}
document.body.appendChild(docFragm);
- cloneNode
var original = document.getElementById('container');
var cloned = original.cloneNode(true);
cloned.setAttribute('width', '50%');
var elem, contents;
for(var i = 0; i < textlist.length; i++) {
elem = document.createElement('p');
contents = document.createTextNode(textlist[i]);
elem.appendChild(contents);
cloned.appendChild(elem);
}
original.parentNode.replaceChild(cloned, original);
- invisible
var posElem = document.getElementById('animation');
posElem.style.display = 'none';
posElem.appendChild(newNodes);
posElem.style.width = '10em';
// Other changes…
posElem.style.display = 'block';// block 塊級元素
- Taking measurements
Taking measurements will force it to reflow
瀏覽器也會cache 操作,一次 reflow.但是進行測量操作時為了獲取准確數據,會強制進行 reflow
style 樣式操作
- 在已知樣式的情況下設置 class
div {
background: #ddd;
color: #000;
border: 1px solid #000;
}
div.highlight {
background: #333;
color: #fff;
border: 1px solid #00f;
}
…
document.getElementById('mainelement').className = 'highlight';
- define a
newstyle attribute for the element
兼容性: - IE的 setAttribute 不支持設置'style'(另外設置"class"屬性,IE為"className")
- 一些老瀏覽器,包括Opera 8,不支持 cssText
- 如果只修改一些style,可以拼接,但是IE6/7/8中 cssText 返回值少了分號
var posElem = document.getElementById('animation');
var newStyle = 'background: ' + newBack + ';' +
'color: ' + newColor + ';' +
'border: ' + newBorder + ';';
if(typeof(posElem.style.cssText) != 'undefined') {
posElem.style.cssText = newStyle;
} else {
posElem.setAttribute('style', newStyle);
}
DOM事件
event 對象
- stopPropagation() 取消冒泡,IE 不支持
- cancelBubble = true 取消冒泡(IE)
- preventDefault() 取消默認行為 IE 不支持
- cancelable = false 表示沒有默認行為 IE 不支持
- returnValue = false 取消默認行為(IE)
- javascript 的 return false 只會阻止默認行為,
- jQuery
- return 則既阻止默認行為又防止冒泡
- stopPropagation 取消冒泡,兼容IE
- preventDefault 取消默認行為,兼容 IE
// 取消冒泡和默認行為
function cancelHandler(event){
if(window.event){
window.event.cancelBubble = true;
window.event.eturnValue = false;
}else{
event.stopPropagation();
event.preventDefault();
}
return false;
// jquery
return false;
}
/*只取消冒泡*/
function stopHandler(event)
window.event?window.event.cancelBubble=true:event.stopPropagation();
// jquery
event.stopPropagation();
}
/*只取消默認行為*/
function cancleDefault(event){
return false;
// with jquery
event.preventDefault();
}
