DOM節點類型 nodeTypehtml
element 1 Node.ELEMENT_NODE 元素節點node
attr 2 Node.ATTRIBUTE_NODE 屬性節點jquery
text 3 Node.TEXT_NODE 文本節點(標籤之間的空白區域也屬於文本節點)數組
comment 8 Node.COMMENT_NODE 註釋節點瀏覽器
document 9 Node.DOCUMENT_NODE 文檔節點(全部文檔之上,即一個頁面中最最前面的位置,在文檔定義的前面)dom
documentType 10 Node.DOCUMENT_TYPE_NODE 文檔類型節點(DOCTYPE)函數
documentFragment 11 Node.DOCUMENT_FRAGMENT_NODE 文檔片斷節點(不屬於文檔樹,是最小片斷,能夠做爲臨時佔位符,將它插入文檔時,只會插入它的子孫元素,而不是它自己)spa
注意:IE8及如下沒有node,使用常量來判斷nodeType會報錯:「Node」未定義3d
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> body{ width:100%; height:100%; } </style> </head> <body> <div id="container"></div> <script> window.onload=function(){ var container=document.getElementById("container"); if(container.nodeType==Node.ELEMENT_NODE){ alert("是元素節點"); } } </script> </body> </html>
所以不建議使用常量來判斷,建議使用數值code
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> body{ width:100%; height:100%; } </style> </head> <body> <div id="container"></div> <script> window.onload=function(){ var container=document.getElementById("container"); // if(container.nodeType==Node.ELEMENT_NODE){ // alert("是元素節點"); // } if(container.nodeType==1){ alert("是元素節點"); } } </script> </body> </html>
nodeName 節點名稱
nodeValue 節點值
.attributes 保存元素的全部屬性,可使用數組下標訪問某一個具體的屬性
.chilsNodes 獲取元素的全部子節點,可使用數組下標訪問某一個具體的屬性
document.doctype 獲取文檔類型節點
document.createDocumentFlagment() 建立文檔片斷
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> body{ width:100%; height:100%; } </style> </head> <body> <!-- 這是一段註釋哈 --> <div id="container">這是裏面的文本鴨</div> <script> window.onload=function(){ var container=document.getElementById("container"); console.log("元素節點:"+container.nodeName+"/"+container.nodeValue);//元素節點:DIV/null var attr=container.attributes[0];//獲取元素的第一個屬性 console.log("屬性節點:"+attr.nodeName+"/"+attr.nodeValue);//屬性節點:id/container var text=container.childNodes[0];//獲取元素的第一個子元素節點 console.log("文本節點:"+text.nodeName+"/"+text.nodeValue);//文本節點:#text/這是裏面的文本鴨 var comment=document.body.childNodes[1];//獲取body元素的第二個子元素節點(第一個子元素節點是空白文本節點) console.log("註釋節點:"+comment.nodeName+"/"+comment.nodeValue);//註釋節點:#comment/ 這是一段註釋哈 var doctype=document.doctype;//獲取body元素的第二個子元素節點(第一個子元素節點是空白文本節點) console.log("文檔類型節點:"+doctype.nodeName+"/"+doctype.nodeValue);//文檔類型節點:html/null var docFragment=document.createDocumentFragment();//獲取body元素的第二個子元素節點(第一個子元素節點是空白文本節點) console.log("文檔片斷節點:"+docFragment.nodeName+"/"+docFragment.nodeValue);//文檔片斷節點:#document-fragment/null } </script> </body> </html>
當script腳本在DOM元素以前,會沒法獲取到DOM元素
由於把js代碼放在head中,代碼順序執行,當頁面在瀏覽器中打開時,會先執行js代碼,再執行body裏面的dom結構。若是js執行時要獲取body中的元素,那麼就會報錯,由於頁面的結構尚未加載進來。
可使用window.onload解決
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> body{ width:100%; height:100%; } </style> <script> window.onload=function(){ var container=document.getElementById("container"); console.log(container); } </script> </head> <body> <!-- 這是一段註釋哈 --> <div id="container">這是裏面的文本鴨</div> </body> </html>
window.onload缺點:等待DOM樹的加載和外部資源所有加載完成
若是頁面引用了不少外部資源,會致使加載慢,影響用戶體驗
最佳解決方案,jquery的$(document).ready()
此處使用原生js仿寫該方法
DOMContentLoaded 加載完dom樹,但尚未開始加載外部資源
IE不支持該方法,使用:document.documentElement.doScroll("left")
監聽document的加載狀態 document.onreadystatechange
document加載完成 document.readyState=="complete"
arguments.callee 調用函數自身
本身寫的DomReady.js
function myReady(fn){ /* 現代瀏覽器操做 */ if(document.addEventListener){ //現代瀏覽器操做 document.addEventListener("DOMContentLoaded",fn,false);//false表示在冒泡階段捕獲 }else{ //IE環境操做 IEContentLoaded(fn); } /* IE環境操做 */ function IEContentLoaded(fn){ // init()--保證fn只調用一次 var loaded=false; var init=function(){ if(!loaded){ loaded=true; fn(); } } // 若是DOM樹加載還沒完成,就不停嘗試 (function(){ try{ // 若是DOM樹加載還沒完成,會拋出異常 document.documentElement.doScroll("left"); }catch(e){ // 嘗試失敗,則再次嘗試 setTimeout(arguments.callee,50); return;//實現遞歸 } //若是沒有拋出異常,則馬上執行init() init(); })(); // DOM樹加載完成以後,調用init()方法 document.onreadystatechange=function(){ if(document.readyState=="complete"){ document.onreadystatechange=null;//清除監聽事件 init(); } } } }
調用該js
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> body{ width:100%; height:100%; } </style> <script src="DomReady.js"></script> <script> myReady(function(){ var container=document.getElementById("container"); console.log(container); }); </script> </head> <body> <!-- 這是一段註釋哈 --> <div id="container">這是裏面的文本鴨</div> </body> </html>
實現各瀏覽器都能成功獲取到~
下面來真實感覺下window.onload 和domReady的區別!!!
使用多張大圖圖片來模擬加載時長
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> body{ width:100%; height:100%; } </style> <script src="DomReady.js"></script> </head> <body> <!-- 這是一段註釋哈 --> <div id="container">這是裏面的文本鴨</div> <img src="source/cat.jpg"> <img src="source/cat.jpg"> <img src="source/cat.jpg"> <img src="source/cat.jpg"> <img src="source/cat.jpg"> <img src="source/cat.jpg"> <img src="source/cat.jpg"> <img src="source/cat.jpg"> <img src="source/cat.jpg"> <img src="source/cat.jpg"> <img src="source/cat.jpg"> <img src="source/cat.jpg"> <img src="source/cat.jpg"> <img src="source/cat.jpg"> <img src="source/cat.jpg"> <img src="source/cat.jpg"> <img src="source/cat.jpg"> <img src="source/cat.jpg"> <script> myReady(function(){ alert("domReady!"); domready=new Date().getTime(); }); window.onload=function(){ alert("windowLoaded!"); windowload=new Date().getTime(); } </script> </body> </html>
發現先彈出domReady
等到圖片加載完成以後,才彈出windowLoaded
證明windowLoaded耗時比較久
元素節點的類型判斷
isElement() 判斷是不是元素節點
isHTML() 判斷是不是html文檔的元素節點
isXML() 判斷是不是xml文檔的元素節點
contains() 判斷元素節點之間是不是包含關係
.nextSibling 獲取元素的兄弟節點
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> body{ width:100%; height:100%; } </style> <script src="DomReady.js"></script> </head> <body> <div id="container">這是裏面的文本鴨</div><!-- 這是一段註釋哈 --> <script> myReady(function(){ function isElement(el){ return !!el && el.nodeType===1; } console.log(isElement(container)); console.log(isElement(container.nextSibling)); }); </script> </body> </html>
該方法有一個Bug,即若是有一個對象設置了nodeType屬性,會致使判斷錯誤
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> body{ width:100%; height:100%; } </style> <script src="DomReady.js"></script> </head> <body> <div id="container">這是裏面的文本鴨</div><!-- 這是一段註釋哈 --> <script> myReady(function(){ function isElement(el){ return !!el && el.nodeType===1; } var obj={ nodeType:1 } console.log(isElement(obj));//true }); </script> </body> </html>
isXML() 最嚴謹的寫法
.createElement() 建立元素
若是不區分大小寫,則爲html文檔的元素節點;
若是區分大小寫,則爲xml文檔的元素節點
.ownerDocument返回元素自身的文檔對象
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> body{ width:100%; height:100%; } </style> <script src="DomReady.js"></script> </head> <body> <div id="container">這是裏面的文本鴨</div><!-- 這是一段註釋哈 --> <script> myReady(function(){ // 判斷是不是元素節點 function isElement(el){ return !!el && el.nodeType==1; } // 判斷是不是xml文檔 function isXML(el){ return el.createElement("p").nodeName!==el.createElement("P").nodeName; } // 判斷是不是html文檔 function isHTML(el){ return el.createElement("p").nodeName===el.createElement("P").nodeName; } // 判斷是不是html文檔的元素節點 function isHTMLNode(el){ if(isElement(el)){ return isHTML(el.ownerDocument); } return false; } console.log(isXML(document));//false console.log(isHTML(document));//true console.log(isHTMLNode(container));//true }); </script> </body> </html>
.containers 判斷某個節點是否包含另外一個節點
谷歌瀏覽器表現正常,而IE瀏覽器要求兩個節點都必須是元素節點
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> body{ width:100%; height:100%; } </style> <script src="DomReady.js"></script> </head> <body> <div class="parent" id="parent"> <div class="child" id="child">這是文本節點</div> </div> <script> myReady(function(){ var parent=document.getElementById("parent"); var child=document.getElementById("child"); console.log(parent.contains(child));//true var text=child.childNodes[0]; console.log(parent.contains(text));//谷歌瀏覽器true,IE瀏覽器爲false }); </script> </body> </html>
接下來給出兼容性寫法
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> body{ width:100%; height:100%; } </style> <script src="DomReady.js"></script> </head> <body> <div class="parent" id="parent"> <div class="child" id="child">這是文本節點</div> </div> <script> myReady(function(){ var parent=document.getElementById("parent"); var child=document.getElementById("child"); console.log(parent.contains(child));//true var text=child.childNodes[0]; console.log(parent.contains(text));//谷歌瀏覽器true,IE瀏覽器爲false function fixContains(pNode,cNode){ try{ while(cNode=cNode.parentNode){ if(pNode===cNode) return true; } return false; }catch(e){ return false; } } console.log(fixContains(parent,text));//谷歌瀏覽器true,IE瀏覽器爲true }); </script> </body> </html>
在全部瀏覽器裏都能返回true,哪怕不是元素節點