天天看點

JavaScript DOM基礎

dom(document object model)即文檔對象模型,針對html和xml文檔的api(應用程式接口)。

一.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       根節點

                                               head                                                body                   子節點1

                            meta                          title                   h1                 p                  ul               子節點2

                                                                                                                        li       li         li             子節點3

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

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

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

                                                                                         元素節點(div)

                                           文本節點  (測試)                                                         屬性節點(title="标簽屬性")

<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:上面的方法,采用的忽略空白檔案節點的方法,把得到元素節點累加到數組裡傳回。那麼還有一種做法是,直接删除空白節點即可。

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]);

四.節點操作

dom不單單可以查找節點,也可以建立節點、複制節點、插入節點、删除節點和替換節點。

節點操作方法

write()

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

createelement()

建立一個元素節點

appendchild()

将新節點追加到子節點清單的末尾

createtextnode()

建立一個檔案節點

insertbefore()

将新節點插入在前面

repalcechild()

将新節點替換舊節點

clonenode()

複制節點

removechild()

移除節點

1.write()方法//一般用于測試 因為會覆寫前面的html

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);

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表示複制内容 false 隻克隆标簽

box.appendchild(clone);//添加到子節點清單末尾

8.removechild()方法

removechild()方法可以把

box.parentnode.removechild(box);//删除指定節點

繼續閱讀