DOM節點型別 nodeType
element 1 Node.ELEMENT_NODE 元素節點
attr 2 Node.ATTRIBUTE_NODE 屬性節點
text 3 Node.TEXT_NODE 文本節點(標簽之間的空白區域也屬于文本節點)
comment 8 Node.COMMENT_NODE 注釋節點
document 9 Node.DOCUMENT_NODE 檔案節點(所有檔案之上,即一個頁面中最最前面的位置,在檔案定義的前面)
documentType 10 Node.DOCUMENT_TYPE_NODE 檔案型別節點(DOCTYPE)
documentFragment 11 Node.DOCUMENT_FRAGMENT_NODE 檔案片段節點(不屬于檔案樹,是最小片段,可以作為臨時占位符,將它插入檔案時,只會插入它的子孫元素,而不是它本身)
注意:IE8及以下沒有node,使用常量來判斷nodeType會報錯:“Node”未定義
<!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>

因此不建議使用常量來判斷,建議使用數值
<!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,哪怕不是元素節點
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/151132.html
標籤:JavaScript
