1. 程式人生 > >深入理解DOM節點型別第五篇——元素節點Element

深入理解DOM節點型別第五篇——元素節點Element

前面的話

  元素節點Element非常常用,是DOM文件樹的主要節點;元素節點是HTML標籤元素的DOM化結果。元素節點主要提供了對元素標籤名、子節點及特性的訪問,本文將詳細介紹元素節點的主要內容

特徵

  元素節點的三個node屬性——nodeType、nodeName、nodeValue分別是1、元素的大寫標籤名和null,其父節點parentNode指向包含該元素節點的元素節點Element或文件節點Document

  [注意]要訪問元素的標籤名可以使用nodeName,也可以使用tagName屬性,這兩個屬性會返回相同的值

<div id="test">
123</div> <script> console.log(test.nodeType);//1 console.log(test.nodeName);//'DIV' console.log(test.nodeValue);//null console.log(test.parentNode);//<body> console.log(test.childNodes);//[text] console.log(test.tagName,test.tagName === test.nodeName);//'DIV' true </script>

子節點

  元素可以有任意數目的子節點和後代節點,因為元素可以是其他元素的子節點。元素的childNodes屬性中包含了它的所有子節點,這些子節點可能是元素、文字註釋、處理指令節點

<ul class="list" id="list">
    <li class="in"></li>
    <li class="in"></li>
</ul>
<script>
var oList = document.getElementById('list');
//IE8-瀏覽器返回2,其他瀏覽器返回5。因為IE8-瀏覽器子節點中不包含空白文字節點
//關於空白文字節點的詳細內容移步至此 console.log(oList.childNodes.length) </script>

相容

  可以通過檢查nodeType屬性來只獲取元素節點

<ul class="list" id="list">
    <li class="in"></li>
    <li class="in"></li>
</ul>
<script>
var oList = document.getElementById('list');
var children = oList.childNodes;
var num = 0;
for(var i = 0; i < children.length; i++){
    if(children[i].nodeType == 1){
        num++;
    }
}
console.log(num);//2   
</script>

特性操作

  每個元素都有一個或多個特性,這些特性的用途是給出相應元素或其內容的附加資訊。操作特性的DOM方法主要有hasAttribute()、getAttribute()、setAttribute()、removeAttribute()四個,可以針對任何特性使用,包括那些以HTMLElement型別屬性的形式定義的特性

hasAttribute()

  hasAttribute()方法返回一個布林值,表示當前元素節點是否包含指定屬性

  [注意]IE7-瀏覽器不支援hasAttribute()方法

<div id="test" class="class1"></div>
<script>
console.log(test.hasAttribute('class'));//true
console.log(test.hasAttribute('title'));//false
</script>

getAttribute()

  getAttribute()方法用於取得特性的值,如果給定名稱的特性不存在或無引數則返回null

<div id="test" class="class1"></div>
<script>
console.log(test.getAttribute('class'));//'class1'
console.log(test.getAttribute('title'));//null
console.log(test.getAttribute('b'));//null
console.log(test.getAttribute(''));//null
</script>

  [注意]元素特性和物件屬性並不相同,二者的區別詳細情況移步至此

setAttribute()

  setAttribute()方法接受兩個引數:要設定的特性名和值,如果已經存在,則替換現有的值。如果特性不存在,setAttribute()則建立該屬性並設定相應的值。該方法無返回值

<div id="box">123</div>
<script>
var oBox = document.getElementById('box');
oBox.setAttribute("id","test");
//注意獲取oBox.id時並不會報錯,因為oBox儲存的是當時id為box的物件,也就是現在id為test的物件
console.log(oBox.id);//test
</script>

  [注意]通過setAttrbute()方法設定的特性名會統一轉換成小寫形式

<div id="box">123</div>
<script>
var oBox = document.getElementById('box');
oBox.setAttribute("ABC","test");
console.log(oBox.getAttribute("ABC"));//test
console.log(oBox.getAttribute("abc"));//test
</script>

bug

  IE7-瀏覽器設定class、style、for、cellspacing、cellpadding、tabindex、readonly、maxlength、rowspan、colspan、usemap、frameborder、contenteditable這13個特性沒有任何效果

<style>
.testClass{
    font-size: 30px;
}
</style>    

<div id="box">123</div>
<script>
//IE7-瀏覽器下沒有任何效果,其他瀏覽器出現紅色背景及30px的文字大小
var oBox = document.getElementById('box');
oBox.setAttribute("class","testClass");
oBox.setAttribute("style","height: 100px; background: red;")
</script>     

  可以利用IE7-瀏覽器下物件屬性和元素特性的混淆bug來設定

<style>
.testClass{
    font-size: 30px;
}
</style>    

<div id="box">123</div>
<script>
var oBox = document.getElementById('box');
oBox.setAttribute("class","testClass");
oBox.setAttribute("style","height: 100px; background: red;");
//IE7下oBox.className的值為undefined
if(!oBox.className){
    oBox.setAttribute("className","testClass");
    oBox.style.setAttribute("cssText","height: 100px; background: red;");
}
</script> 

removeAttribute()

  removeAttribute()方法用於徹底刪除元素的特性,這個方法不僅會徹底刪除元素的特性值,還會刪除元素特性。該方法無返回值

<div class="box" id="box"></div>
<script>
var oBox = document.getElementById('box');
console.log(oBox.getAttribute("id"));//box
console.log(oBox.removeAttribute("id"));//undefined
console.log(oBox.getAttribute("id"));//null    
</script>

attributes屬性

  元素節點Element是唯一一個使用attributes屬性的DOM節點型別。attributes屬性中包含一個NamedNodeMap,與NodeList類似,也是一個動態的集合。元素的每一個特性都由一個Attr節點表示,每個節點都儲存在NamedNodeMap物件中,每個節點的nodeName就是特性的名稱,節點的nodeValue就是特性的值

  attributes屬性包含以下四個方法

getNamedItem(name)

  getNamedItem(name)方法返回nodeName屬性等於name的節點

<div class="box" id="box" name="abc" index="123" title="test"></div>
<script>
var oBox = document.getElementById('box');
console.log(oBox.attributes);//NamedNodeMap {0: class, 1: id, 2: name, 3: index, 4: title}
console.log(oBox.attributes.getNamedItem("index"));//index='123'
console.log(oBox.attributes.getNamedItem("index").nodeName);//'index'
console.log(oBox.attributes.getNamedItem("index").nodeValue);//'123'
console.log(oBox.attributes.index);//index='123'
</script>

removeNamedItem(name)

  removeNamedItem(name)方法從列表中移除nodeName屬性等於name的節點,並返回該節點

<div class="box" id="box" name="abc" index="123" title="test"></div>
<script>
var oBox = document.getElementById('box');
console.log(oBox.attributes);//NamedNodeMap {0: class, 1: id, 2: name, 3: index, 4: title}
console.log(oBox.attributes.getNamedItem("index"));//index='123'
console.log(oBox.attributes.removeNamedItem("index"));//index='123'
console.log(oBox.attributes.getNamedItem("index"));//null
</script>

setNamedItem(node)

  setNamedItem(node)方法向列表中新增節點,該方法無返回值

<div class="box" id="box" name="abc" index="123" title="test"></div>
<script>
var oBox = document.getElementById('box');
console.log(oBox.attributes);//NamedNodeMap {0: class, 1: id, 2: name, 3: index, 4: title}
var oldItem = oBox.attributes.removeNamedItem("index");
console.log(oBox.attributes.getNamedItem("index"));//null
console.log(oldItem);//index='123'
console.log(oBox.attributes.setNamedItem(oldItem));//null
console.log(oBox.attributes.getNamedItem("index"));//index='123'
</script>

item(pos)

  item(pos)方法返回位於數字pos位置處的節點,也可以用方括號法[]簡寫

<div class="box" id="box" name="abc" index="123" title="test"></div>
<script>
var oBox = document.getElementById('box');
console.log(oBox.attributes);//NamedNodeMap {0: class, 1: id, 2: name, 3: index, 4: title}
console.log(oBox.attributes.item(2));//name="abc"
console.log(oBox.attributes[2]);//name="abc"
</script>

遍歷

  attributes屬性主要用於特性遍歷。在需要將DOM結構序列化為HTML字串時,多數都會涉及遍歷元素特性

function outputAttributes(element){
    var pairs = new Array(),attrName,attrValue,i,len;
    for(i = 0,len=element.attributes.length;i<len;i++){
        attrName = element.attributes[i].nodeName;
        attrValue = element.attributes[i].nodeValue;
        pairs.push(attrName +"=\"" + attrValue + "\"");
    }
    return pairs.join(" ");
}

  針對attributes物件中的特性,不同瀏覽器返回的順序不同

<div class="box" id="box" name="abc" index="123" title="test"></div>
<script>
function outputAttributes(element){
    var pairs = new Array(),attrName,attrValue,i,len;
    for(i = 0,len=element.attributes.length;i<len;i++){
        attrName = element.attributes[i].nodeName;
        attrValue = element.attributes[i].nodeValue;
        pairs.push(attrName +"=\"" + attrValue + "\"");
    }
    return pairs.join(" ");
}
//(chrome\safari)class="box" id="box" name="abc" index="123" title="test"
//(firefox)title="test" index="123" name="abc" id="box" class="box"
//(IE8+)title="test" class="box" id="box" index="123" name="abc"
//(IE7-)輸出所有的特性
console.log(outputAttributes(document.getElementById("box")))
</script>

  由上面結果看出,IE7-瀏覽器會返回HTML元素中所有可能的特性,包括沒有指定的特性

specified

  可以利用特性節點的specified屬性來解決IE7-瀏覽器的這個問題。如果specified屬性的值為true,則意味著該屬性被設定過。在IE中,所有未設定過的特性的該屬性值都是false。而在其他瀏覽器中,任何特性節點的specified值始終為true

<div id="box" name="abc" index="123" title="test"></div>
<script>
var oBox = document.getElementById('box');
var yesItem = oBox.attributes.getNamedItem("index");
var noItem = oBox.attributes.getNamedItem("onclick");
//所有瀏覽器瀏覽器都返回true
console.log(yesItem.specified);
//IE7-瀏覽器返回false,而其他瀏覽器報錯,noItem不存在
console.log(noItem.specified);
</script>
<div class="box" id="box" name="abc" index="123" title="test"></div>
<script>
function outputAttributes(element){
    var pairs = new Array(),attrName,attrValue,i,len;
    for(i = 0,len=element.attributes.length;i<len;i++){
        attrName = element.attributes[i].nodeName;
        attrValue = element.attributes[i].nodeValue;
        if(element.attributes[i].specified){
            pairs.push(attrName +"=\"" + attrValue + "\"");    
        }
    }
    return pairs.join(" ");
}
//所有瀏覽器下都返回title="test" class="box" id="box" index="123" name="abc"(順序不一樣)
console.log(outputAttributes(document.getElementById("box")))
</script> 

最後

  如果從頭到尾看完這篇博文,會發現全篇篇幅最多的內容是特性的設定。特性設定不是應該在特性節點上嗎?特性節點可以設定,但是使用元素節點來操作特性更方便。元素節點的內容還包括元素節點的操作,但是由於在節點操作博文中已經詳細介紹過,就不再贅述

  下一篇將介紹特性節點

  歡迎交流