1. 程式人生 > >javascript DOM基礎操作

javascript DOM基礎操作

sna fir del 非ie 麻煩 iou 沒有 mode 節點和

DOM(Document Object Model)即文檔對象模型,針對HTML和XML文檔的API(應用程序接口)。DOM描繪了一個層次化的節點樹,運行開發人員添加、移除和修改頁面的某一部分。DOM脫胎於Netscape及微軟公司創始的DHTML(動態HTML),但現在它已經成為表現和操作頁面標記的真正跨平臺、語言中立的方式。

一.DOM介紹

DOM中的三個字母,D(文檔)可以理解為整個Web加載的網頁文檔;O(對象)可以理解為類似window對象之類的東西,可以調用屬性和方法,這裏我們說的是document對象;M(模型)可以理解為網頁文檔的樹型結構。

DOM有三個等級,分別是DOM1、DOM2、DOM3,並且DOM1在1998年10月成為W3C標準。DOM1所支持的瀏覽器包括IE6+、Firefox、Safari、Chrome和Opera1.7+。

PS:IE中的所有DOM對象都是以COM對象的形式實現的,這意味著IE中的DOM可能會和其他瀏覽器有一定的差異。

1.節點

加載HTML頁面時,Web瀏覽器生成一個樹型結構,用來表示頁面內部結構。DOM將這種樹型結構理解為由節點組成。

節點樹

技術分享圖片

從上圖的樹型結構,我們理解幾個概念,html標簽沒有父輩,沒有兄弟,所以html標簽為根標簽。head標簽是html子標簽,meta和title標簽之間是兄弟關系。如果把每個標簽當作一個節點的話,那麽這些節點組合成了一棵節點樹。

PS:後面我們經常把標簽稱作為元素,是一個意思。

1.節點種類:元素節點、文本節點、屬性節點。

<div title="屬性節點">測試Div</div>

技術分享圖片

二.查找元素

W3C提供了比較方便簡單的定位節點的方法和屬性,以便我們快速的對節點進行操作。分別為:getElementById()、getElementsByTagName()、getElementsByName()、getAttribute()、setAttribute()和removeAttribute()。

元素節點方法

方法

說明

getElementById()

獲取特定ID元素的節點

getElementsByTagName()

獲取相同元素的節點列表

getElementsByName()

獲取相同名稱的節點列表

getAttribute()

獲取特定元素節點屬性的值

setAttribute()

設置特定元素節點屬性的值

removeAttribute()

移除特定元素節點屬性

1.getElementById()方法

getElementById()方法,接受一個參數:獲取元素的ID。如果找到相應的元素則返回該元素的HTMLDivElement對象,如果不存在,則返回null。

document.getElementById(‘box‘); //獲取id為box的元素節點

PS:上面的例子,默認情況返回null,這無關是否存在id="box"的標簽,而是執行順序問題。解決方法,1.把script調用標簽移到html末尾即可;2.使用onload事件來處理JS,等待html加載完畢再加載onload事件裏的JS。

window.onload = function () { //預加載html後執行

document.getElementById(‘box‘);

};

PS:id表示一個元素節點的唯一性,不能同時給兩個或以上的元素節點創建同一個命名的id。某些低版本的瀏覽器會無法識別getElementById()方法,比如IE5.0-,這時需要做一些判斷,可以結合上章的瀏覽器檢測來操作。

if (document.getElementById) { //判斷是否支持getElementById

alert(‘當前瀏覽器支持getElementById‘);

}

當我們通過getElementById()獲取到特定元素節點時,這個節點對象就被我們獲取到了,而通過這個節點對象,我們可以訪問它的一系列屬性。

元素節點屬性

屬性

說明

tagName

獲取元素節點的標簽名

innerHTML

獲取元素節點裏的內容,非W3C DOM規範

document.getElementById(‘box‘).tagName; //DIV

document.getElementById(‘box‘).innerHTML; //測試Div

HTML屬性的屬性

屬性

說明

id

元素節點的id名稱

title

元素節點的title屬性值

style

CSS內聯樣式屬性值

className

CSS元素的類

document.getElementById(‘box‘).id; //獲取id

document.getElementById(‘box‘).id = ‘person‘; //設置id

document.getElementById(‘box‘).title; //獲取title

document.getElementById(‘box‘).title = ‘標題‘ //設置title

document.getElementById(‘box‘).style; //獲取CSSStyleDeclaration對象

document.getElementById(‘box‘).style.color; //獲取style對象中color的值

document.getElementById(‘box‘).style.color = ‘red‘; //設置style對象中color的值

document.getElementById(‘box‘).className; //獲取class

document.getElementById(‘box‘).className = ‘box‘; //設置class

alert(document.getElementById(‘box‘).bbb); //獲取自定義屬性的值,非IE不支持

2.getElementsByTagName()方法

getElementsByTagName()方法將返回一個對象數組HTMLCollection(NodeList),這個數組保存著所有相同元素名的節點列表。

document.getElementsByTagName(‘*‘); //獲取所有元素

PS:IE瀏覽器在使用通配符的時候,會把文檔最開始的html的規範聲明當作第一個元素節點。

document.getElementsByTagName(‘li‘); //獲取所有li元素,返回數組

document.getElementsByTagName(‘li‘)[0]; //獲取第一個li元素,HTMLLIElement

document.getElementsByTagName(‘li‘).item(0) //獲取第一個li元素,HTMLLIElement

document.getElementsByTagName(‘li‘).length; //獲取所有li元素的數目

PS:不管是getElementById還是getElementsByTagName,在傳遞參數的時候,並不是所有瀏覽器都必須區分大小寫,為了防止不必要的錯誤和麻煩,我們必須堅持養成區分大小寫的習慣。

3.getElementsByName()方法

getElementsByName()方法可以獲取相同名稱(name)的元素,返回一個對象數組HTMLCollection(NodeList)。

document.getElementsByName(‘add‘) //獲取input元素

document.getElementsByName(‘add‘)[0].value //獲取input元素的value值

document.getElementsByName(‘add‘)[0].checked //獲取input元素的checked值

PS:對於並不是HTML合法的屬性,那麽在JS獲取的兼容性上也會存在差異,IE瀏覽器支持本身合法的name屬性,而不合法的就會出現不兼容的問題。

4.getAttribute()方法

getAttribute()方法將獲取元素中某個屬性的值。它和直接使用.屬性獲取屬性值的方法有一定區別。

document.getElementById(‘box‘).getAttribute(‘id‘);//獲取元素的id值

document.getElementById(‘box‘).id; //獲取元素的id值

document.getElementById(‘box‘).getAttribute(‘mydiv‘);//獲取元素的自定義屬性值

document.getElementById(‘box‘).mydiv //獲取元素的自定義屬性值,非IE不支持

document.getElementById(‘box‘).getAttribute(‘class‘);//獲取元素的class值,IE不支持

document.getElementById(‘box‘).getAttribute(‘className‘);//非IE不支持

PS:HTML通用屬性style和onclick,IE7更低的版本style返回一個對象,onclick返回一個函數式。雖然IE8已經修復這個bug,但為了更好的兼容,開發人員只有盡可能避免使用getAttribute()訪問HTML屬性了,或者碰到特殊的屬性獲取做特殊的兼容處理。

5.setAttribute()方法

setAttribute()方法將設置元素中某個屬性和值。它需要接受兩個參數:屬性名和值。如果屬性本身已存在,那麽就會被覆蓋。

document.getElementById(‘box‘).setAttribute(‘align‘,‘center‘);//設置屬性和值

document.getElementById(‘box‘).setAttribute(‘bbb‘,‘ccc‘);//設置自定義的屬性和值

PS:在IE7及更低的版本中,使用setAttribute()方法設置class和style屬性是沒有效果的,雖然IE8解決了這個bug,但還是不建議使用。

6.removeAttribute()方法

removeAttribute()可以移除HTML屬性。

document.getElementById(‘box‘).removeAttribute(‘style‘);//移除屬性

PS:IE6及更低版本不支持removeAttribute()方法。

三.DOM節點

1.node節點屬性

節點可以分為元素節點、屬性節點和文本節點,而這些節點又有三個非常有用的屬性,分別為:nodeName、nodeType和nodeValue。

信息節點屬性

節點類型

nodeName

nodeType

nodeValue

元素

元素名稱

1

null

屬性

屬性名稱

2

屬性值

文本

#text

3

文本內容(不包含html)

document.getElementById(‘box‘).nodeType; //1,元素節點

2.層次節點屬性

節點的層次結構可以劃分為:父節點與子節點、兄弟節點這兩種。當我們獲取其中一個元素節點的時候,就可以使用層次節點屬性來獲取它相關層次的節點。

層次節點屬性

屬性

說明

childNodes

獲取當前元素節點的所有子節點

firstChild

獲取當前元素節點的第一個子節點

lastChild

獲取當前元素節點的最後一個子節點

ownerDocument

獲取該節點的文檔根節點,相當與document

parentNode

獲取當前節點的父節點

previousSibling

獲取當前節點的前一個同級節點

nextSibling

獲取當前節點的後一個同級節點

attributes

獲取當前元素節點的所有屬性節點集合

1.childNodes屬性

childeNodes屬性可以獲取某一個元素節點的所有子節點,這些子節點包含元素子節點和文本子節點。

var box = document.getElementById(‘box‘); //獲取一個元素節點

alert(box.childNodes.length); //獲取這個元素節點的所有子節點

alert(box.childNodes[0]); //獲取第一個子節點對象

PS:使用childNodes[n]返回子節點對象的時候,有可能返回的是元素子節點,比如 HTMLElement;也有可能返回的是文本子節點,比如Text。元素子節點可以使用nodeName或者tagName獲取標簽名稱,而文本子節點可以使用nodeValue獲取。

for (var i = 0; i < box.childNodes.length; i ++) {

//判斷是元素節點,輸出元素標簽名

if (box.childNodes[i].nodeType === 1) {

alert(‘元素節點:‘ + box.childNodes[i].nodeName);

//判斷是文本節點,輸出文本內容

} else if (box.childNodes[i].nodeType === 3) {

alert(‘文本節點:‘ + box.childNodes[i].nodeValue);

}

}

PS:在獲取到文本節點的時候,是無法使用innerHTML這個屬性輸出文本內容的。這個非標準的屬性必須在獲取元素節點的時候,才能輸出裏面包含的文本。

alert(box.innerHTML); //innerHTML和nodeValue第一個區別

PS:innerHTML和nodeValue第一個區別,就是取值的。那麽第二個區別就是賦值的時候,nodeValue會把包含在文本裏的HTML轉義成特殊字符,從而達到形成單純文本的效果。

box.childNodes[0].nodeValue = ‘<strong>abc</strong>‘;//結果為:<strong>abc</strong>

box.innerHTML = ‘<strong>abc</strong>‘; //結果為:abc

2.firstChild和lastChild屬性

firstChild用於獲取當前元素節點的第一個子節點,相當於childNodes[0];lastChild用於獲取當前元素節點的最後一個子節點,相當於childNodes[box.childNodes.length - 1]。

alert(box.firstChild.nodeValue); //獲取第一個子節點的文本內容

alert(box.lastChild.nodeValue); //獲取最後一個子節點的文本內容

3.ownerDocument屬性

ownerDocument屬性返回該節點的文檔對象根節點,返回的對象相當於document。

alert(box.ownerDocument === document); //true,根節點

4.parentNode、previousSibling、nextSibling屬性

parentNode屬性返回該節點的父節點,previousSibling屬性返回該節點的前一個同級節點,nextSibling屬性返回該節點的後一個同級節點。

alert(box.parentNode.nodeName); //獲取父節點的標簽名

alert(box.lastChild.previousSibling); //獲取前一個同級節點

alert(box.firstChild.nextSibling); //獲取後一個同級節點

5.attributes屬性

attributes屬性返回該節點的屬性節點集合。

document.getElementById(‘box‘).attributes //NamedNodeMap

document.getElementById(‘box‘).attributes.length;//返回屬性節點個數

document.getElementById(‘box‘).attributes[0]; //Attr,返回最後一個屬性節點

document.getElementById(‘box‘).attributes[0].nodeType; //2,節點類型

document.getElementById(‘box‘).attributes[0].nodeValue; //屬性值

document.getElementById(‘box‘).attributes[‘id‘]; //Attr,返回屬性為id的節點

document.getElementById(‘box‘).attributes.getNamedItem(‘id‘); //Attr

6.忽略空白文本節點

var body = document.getElementsByTagName(‘body‘)[0];//獲取body元素節點

alert(body.childNodes.length); //得到子節點個數,IE3個,非IE7個

PS:在非IE中,標準的DOM具有識別空白文本節點的功能,所以在火狐瀏覽器是7個,而IE自動忽略了,如果要保持一致的子元素節點,需要手工忽略掉它。

function filterSpaceNode(nodes) {

var ret = []; //新數組

for (var i = 0; i < nodes.length; i ++) {

//如果識別到空白文本節點,就不添加數組

if (nodes[i].nodeType == 3 && /^\s+$/.test(nodes[i].nodeValue)) continue;

//把每次的元素節點,添加到數組裏

ret.push(nodes[i]);

}

return ret;

}

PS:上面的方法,采用的忽略空白文件節點的方法,把得到元素節點累加到數組裏返回。那麽還有一種做法是,直接刪除空白節點即可。

function filterSpaceNode(nodes) {

for (var i = 0; i < nodes.length; i ++) {

if (nodes[i].nodeType == 3 && /^\s+$/.test(nodes[i].nodeValue)) {

//得到空白節點之後,移到父節點上,刪除子節點

nodes[i].parentNode.removeChild(nodes[i]);

}

}

return nodes;

}

PS:如果firstChild、lastChild、previousSibling和nextSibling在獲取節點的過程中遇到空白節點,我們該怎麽處理掉呢?

function removeWhiteNode(nodes) {

for (var i = 0; i < nodes.childNodes.length; i ++) {

if (nodes.childNodes[i].nodeType === 3 &&

/^\s+$/.test(nodes.childNodes[i].nodeValue)) {

nodes.childNodes[i].parentNode.removeChild(nodes.childNodes[i]);

}

}

return nodes;

}

四.節點操作

DOM不單單可以查找節點,也可以創建節點、復制節點、插入節點、刪除節點和替換節點。

節點操作方法

方法

說明

write()

這個方法可以把任意字符串插入到文檔中

createElement()

創建一個元素節點

appendChild()

將新節點追加到子節點列表的末尾

createTextNode()

創建一個文件節點

insertBefore()

將新節點插入在前面

repalceChild()

將新節點替換舊節點

cloneNode()

復制節點

removeChild()

移除節點

1.write()方法

write()方法可以把任意字符串插入到文檔中去。

document.write(‘<p>這是一個段落!</p>‘)‘ ; //輸出任意字符串

2.createElement()方法

createElement()方法可以創建一個元素節點。

document.createElement(‘p‘); //創建一個元素節點

3.appendChild()方法

appendChild()方法講一個新節點添加到某個節點的子節點列表的末尾上。

var box = document.getElementById(‘box‘); //獲取某一個元素節點

var p = document.createElement(‘p‘); //創建一個新元素節點<p>

box.appendChild(p); //把新元素節點<p>添加子節點末尾

4.createTextNode()方法

createTextNode()方法創建一個文本節點。

var text = document.createTextNode(‘段落‘); //創建一個文本節點

p.appendChild(text); //將文本節點添加到子節點末尾

5.insertBefore()方法

insertBefore()方法可以把節點創建到指定節點的前面。

box.parentNode.insertBefore(p, box); //把<div>之前創建一個節點

PS:insertBefore()方法可以給當前元素的前面創建一個節點,但卻沒有提供給當前元素的後面創建一個節點。那麽,我們可以用已有的知識創建一個insertAfter()函數。

function insertAfter(newElement, targetElement) {

//得到父節點

var parent = targetElement.parentNode;

//如果最後一個子節點是當前元素,那麽直接添加即可

if (parent.lastChild === targetElement) {

parent.appendChild(newElement);

} else {

//否則,在當前節點的下一個節點之前添加

parent.insertBefore(newElement, targetElement.nextSibling);

}

}

PS:createElement在創建一般元素節點的時候,瀏覽器的兼容性都還比較好。但在幾個特殊標簽上,比如iframe、input中的radio和checkbox、button元素中,可能會在IE6,7以下的瀏覽器存在一些不兼容。

var input = null;

if (BrowserDetect.browser == ‘Internet Explorer‘ && BrowserDetect.version <= 7) {

//判斷IE6,7,使用字符串的方式

input = document.createElement("<input type=\"radio\" name=\"sex\">");

} else {

//標準瀏覽器,使用標準方式

input = document.createElement(‘input‘);

input.setAttribute(‘type‘, ‘radio‘);

input.setAttribute(‘name‘, ‘sex‘);

}

document.getElementsByTagName(‘body‘)[0].appendChild(input);

6.repalceChild()方法

replaceChild()方法可以把節點替換成指定的節點。

box.parentNode.replaceChild(p,box); //把<div>換成了<p>

7.cloneNode()方法

cloneNode()方法可以把子節點復制出來。

var box = document.getElementById(‘box‘);

var clone = box.firstChild.cloneNode(true); //獲取第一個子節點,true表示復制內容

box.appendChild(clone); //添加到子節點列表末尾

8.removeChild()方法

removeChild()方法可以把

box.parentNode.removeChild(box); //刪除指定節點

綜合應用 Q:節點增、刪、替換、插入 A:1、創建節點
var oP = document.createElement("p");
var oT = document.createTextNode("寫入的文本");
oP.appendChild(oT);
document.body.appendChild(oP);

2、刪除節點

function RemoveNode(){
     var oNewP = document.getElementsByTagName("p")[0];
     oNewP.parentNode.removeChild(oNewP);
}

3、替換

技術分享圖片
function ReplaceNode(){
     var oNewP = document.getElementsByTagName("p")[0];
     var oNewDiv = document.createElement("div");
     oNewDiv.innerHTML = "<p>文字</p>";
     oNewP.parentNode.replaceChild(oNewDiv,oNewP);
}
技術分享圖片

4、插入

技術分享圖片
function InsertNode(){
    var oNewP = document.getElementsByTagName("p")[0];
    var oNewDiv = document.crenteElement("div");
    oNewDiv.innerHTML = "<br/>文字";
   oNewP.parentNode.insertBefoe(oNewDiv,oNewP);
}
技術分享圖片

javascript DOM基礎操作