你不知道的JavaScript--Item32 DOM基礎詳解2
先上幾張圖簡要看看DOM的一些方法屬性:
大概這些就是常用的,下面具體聊聊。
節點型別的判斷
其中元素節點Element的判定最為重要,下面給出4個主要的方法;
1、如何判斷節點是元素節點
可以用isElement()方法
<div id="test">aaa</div>
<!--這是一個註釋節點-->
<script>
var isElement = function (el){
return !!el && el.nodeType === 1;
}
var a = {
nodeType: 1
}
console.log(isElement(document.getElementById("test")));//true
console.log(isElement(document.getElementById("test").nextSibling));//false
//但是很容易偽造一個假的“物件節點”
console.log(isElement(a));
</script>
所以要避免這個的偽造,可以重寫isElement()方法
<div id="test">aaa</div>
<!--這是一個註釋節點-->
<script >
var testDiv = document.createElement('div');
var isElement = function (obj) {
if (obj && obj.nodeType === 1) {//先過濾最簡單的
if( window.Node && (obj instanceof Node )){ //如果是IE9,則判定其是否Node的例項
return true; //由於obj可能是來自另一個文件物件,因此不能輕易返回false
}
try {//最後以這種效率非常差但肯定可行的方案進行判定
testDiv.appendChild(obj);
testDiv.removeChild(obj);
} catch (e) {
return false;
}
return true;
}
return false;
}
var a = {
nodeType: 1
}
console.log(isElement(document.getElementById("test")));
console.log(isElement(document.getElementById("test").nextSibling));
console.log(isElement(a));
</script>
2、如何判斷節點是html或xml元素節點
XML與html物件均支援createElement()方法,通過比較建立的元素時傳入引數的【大小寫】不同的情況下,元素的nodeName是否相同來判斷是哪一種文件物件。如果nodeName相同則為html物件,反之為XML物件。
1、首先看一下Sizzle, jQuery自帶的選擇器引擎
//Sizzle, jQuery自帶的選擇器引擎
var isXML = function(elem) {
var documentElement = elem && (elem.ownerDocument || elem).documentElement;
return documentElement ? documentElement.nodeName !== "HTML" : false;
};
console.log(isXML(document.getElementById("test")));
//但這樣不嚴謹,因為XML的根節點,也可能是HTML標籤,比如這樣建立一個XML文件
try {
var doc = document.implementation.createDocument(null, 'HTML', null);
console.log(doc.documentElement);
console.log(isXML(doc));
} catch (e) {
console.log("不支援creatDocument方法");
}
2、我們看看mootools的slick選擇器引擎的原始碼:
var isXML = function(document) {
return (!!document.xmlVersion) || (!!document.xml) || (toString.call(document) == '[object XMLDocument]')
|| (document.nodeType == 9 && document.documentElement.nodeName != 'HTML');
};
//精簡版
var isXML = window.HTMLDocument ? function(doc) {
return !(doc instanceof HTMLDocument);
} : function(doc) {
return "selectNodes" in doc;
}
3、自己實現的方法—最簡單
var isXML = function(doc) {
return doc.createElement("p").nodeName !== doc.createElement("P").nodeName;
}
那接下來判斷html節點時,就非常簡單了
var isHTML = function(doc) {
return doc.createElement("p").nodeName === doc.createElement("P").nodeName;
}
console.log(isHTML(document));
3、判斷節點間的包含關係:
現代瀏覽器可以用contains()方法,aNode.contains(bNode)判斷是否包含a>b。
<div id="p-node">
<div id="c-node">子節點內容</div>
</div>
<script>
var pNode = document.getElementById("p-node");
var cNode = document.getElementById("c-node").childNodes[0];
alert(document.contains(pNode));//但是在IE8瀏覽器不支援
alert(pNode.contains(cNode));
</script>
但IE不支援文件型別節點和文字型別節點包含關係的判斷,可以自定義實現一個相容各瀏覽器的判斷方法。
自定義實現fixContains()方法是對這個問題的修復。
<div id="p-node">
<div id="c-node">子節點內容</div>
</div>
<script>
//判斷節點a包含節點b的方法,即a和b的父節點比較;
function fixContains(a, b) {
try {
while ((b = b.parentNode)){
if (b === a){
return true;
}
}
return false;
} catch (e) {
return false;
}
}
var pNode = document.getElementById("p-node");
var cNode = document.getElementById("c-node").childNodes[0];
alert(fixContains(pNode, cNode));
//alert(fixContains(document, cNode));
</script>
節點繼承層次與巢狀規則
1、DOM節點繼承層次
1、文字節點繼承層次—-有6層關係
2、元素節點繼承層次—-有7層關係
console.log(Object.getOwnPropertyNames(document.createElement("p").__proto__));//第一層有兩個屬性
console.log(Object.getOwnPropertyNames(document.createElement("p").__proto__.__proto__));//第二層有82個屬性
1個空div的自有屬性有如此之多
所以就有了現在的一些MVVM框架來管理這些DOM節點層次,比如reactjs 虛擬dom加速。
2、HTML巢狀規則
1、塊狀元素和內聯元素
塊狀元素
一般是其他元素的容器,可容納內聯元素和其他塊狀元素,塊狀元素排斥其他元素與其位於同一行,寬度(width)高度(height)起作用。
常見塊狀元素塊級元素—h1,h2,h3,h4,h5,h6,hr,div,fieldset,form,dl,address,ol,p,table,ul,pre
等
block元素的特點:
- 總是另起一行開始;
- 高度,行高以及頂、底邊距都可控制;
- 寬度預設是它所在容器的100%,除非設定一個寬度。
內聯元素
內聯元素只能容納文字或者其他內聯元素,它允許其他內聯元素與其位於同一行,但寬度(width)高度(height)不起作用。
常見內聯元素為—a,b,br,em,i,img,input,strong,textarea,span,label
等常見
inline元素的特點:
- 和其它元素都在一行上;
- 高度,行高以及頂、底邊距不可改變;
- 寬度就是它所容納的文字或圖片的寬度,不可改變。
他們兩個的區別:
- 塊級元素一般用來搭建網站架構、佈局、承載內容
- 內聯元素一般用來在網站內容中的某些細節或者部位,用以“強調、區分樣式、上標、下標、錨點”等等。
- 它們可以互相轉換。
display:inline|block
- 塊級元素的特點:每一個塊級元素都識從一個新行開始顯示,其後的元素需要另起一行
好了 簡單地說了一下塊級元素和內聯元素,下面我們開始我們的重點—–巢狀規則:
3、巢狀規則
塊級元素可以包含內聯元素或某些塊級元素,但內聯元素不能包含塊級元素,它只能包含其它內聯元素。
塊級元素不能放在p裡面。
有幾個特殊的塊級元素只能包含內聯元素,不能包含塊級元素。如h1,h2,h3,h4,h5,h6,p,dt
li內可以包含div
塊級元素與塊級元素並列、內聯元素與內聯元素並列。(錯誤的:<div><h2></h2><span></span></div>
)
一張圖瞭解OUTHTML和innerText、innerHTML: