瀏覽器DOM操作


HTML

- innerHTML:內部HTML,content<br/>;
- outerHTML:外部HTML,<div>content<br/></div>;
- innerText:不會返回隱藏元素的文本,受 CSS 樣式的影響,它會觸發重排(reflow);IE11及以下,不僅會移除當前元素的子節點,而且還會永久性地破壞所有后代文本節點
- textContent,會獲取所有元素的內容,包括 css內容;對比innerText,不會引起重排;兼容性: IE9開始支持
- outerText:outerText 賦值時會把整個標簽一起賦值掉;非標准屬性,不要在生產環境中使用!

jQueryhtml()會調用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 new style 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();
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM