一螃概、 DOM
DOM
(文檔對(duì)象模型)是針對(duì)HTML
和XML
文檔的一個(gè)API
(應(yīng)用程序編程接口)砍聊。DOM
描繪了一個(gè)層次化的節(jié)點(diǎn)樹丈氓,允許開發(fā)人員添加、移除和修改頁面的某一部分宫纬。DOM
脫胎于Netscape 及微軟公司創(chuàng)始的DHTML
(動(dòng)態(tài)HTML
)焚挠,但現(xiàn)在它已經(jīng)成為表現(xiàn)和操作頁面標(biāo)記的真正的跨平臺(tái)、語言中立的方式漓骚。
Node類型
DOM1
級(jí)定義了一個(gè)Node
接口蝌衔,該接口將由DOM
中的所有節(jié)點(diǎn)類型實(shí)現(xiàn)榛泛。每個(gè)節(jié)點(diǎn)都有一個(gè)nodeType
屬性,用于表明節(jié)點(diǎn)的類型胚委。節(jié)點(diǎn)類型由在Node 類型中定義的下列12 個(gè)數(shù)值常量來表示挟鸠,任何節(jié)點(diǎn)類型必居其一:
- 節(jié)點(diǎn)關(guān)系
每個(gè)節(jié)點(diǎn)都有一個(gè)childNodes
屬性,其中保存著一個(gè)NodeList
對(duì)象亩冬。NodeList
是一種類數(shù)組對(duì)象(可以通過下標(biāo)訪問艘希,有length
屬性,但它并不是Array
的實(shí)例)硅急,用于保存一組有序的節(jié)點(diǎn)覆享,可以通過位置(索引 / 方括號(hào)寫法)來訪問這些節(jié)點(diǎn)。NodeList
對(duì)象的獨(dú)特之處在于营袜,它實(shí)際上是基于DOM
結(jié)構(gòu)動(dòng)態(tài)執(zhí)行查詢的結(jié)果撒顿,因此DOM
結(jié)構(gòu)的變化能夠自動(dòng)反映在NodeList
對(duì)象中。我們常說荚板,NodeList
是有生命凤壁、有呼吸的對(duì)象,而不是在我們第一次訪問它們的某個(gè)瞬間拍攝下來的一張快照跪另。
如何訪問保存在NodeList
中的節(jié)點(diǎn)——可以通過方括號(hào)拧抖,也可以使用item()
方法。
var firstChild = someNode.childNodes[0];
var secondChild = someNode.childNodes.item(1);
var count = someNode.childNodes.length;
使用Array.prototype.slice()
方法可以將NodeList
對(duì)象轉(zhuǎn)換為數(shù)免绿。
var arrayOfNodes = Array.prototype.slice.call(someNode.childNodes,0);
-
節(jié)點(diǎn)關(guān)系的引用屬性
-
parentNode
:該屬性指向文檔樹中的父節(jié)點(diǎn) -
previousSibling
:該屬性指向文檔書中的前一個(gè)兄弟節(jié)點(diǎn)唧席,第一個(gè)節(jié)點(diǎn)的previousSibling
屬性值為null
-
nextSibling
:該屬性指向文檔書中的前一個(gè)兄弟節(jié)點(diǎn),最后一個(gè)節(jié)點(diǎn)的nextSibling
屬性值為null
- 父節(jié)點(diǎn)的
firstChild
和lastChild
屬性分別指向其childNodes
列表中的第一個(gè)和最后一個(gè)節(jié)點(diǎn) 中,someNode.firstChild
的值始終等于someNode.childNodes[0]
嘲驾, 而someNode.lastChild
的值始終等于someNode.childNodes [someNode.childNodes.length-1]
淌哟。
-
-
操作子節(jié)點(diǎn)
-
appendChild()
:用于向childNodes
列表的末尾添加一個(gè)節(jié)點(diǎn)。添加節(jié)點(diǎn)后辽故,childNodes
的新增節(jié)點(diǎn)徒仓、父節(jié)點(diǎn)及以前的最后一個(gè)子節(jié)點(diǎn)的關(guān)系指針都會(huì)相應(yīng)地得到更新。更新完成后誊垢,appendChild()
返回新增的節(jié)點(diǎn)蓬衡。如果傳入到appendChild()
中的節(jié)點(diǎn)已經(jīng)是文檔的一部分了,那么該節(jié)點(diǎn)就會(huì)成為父節(jié)點(diǎn)的最后一個(gè)子節(jié)點(diǎn)彤枢。 -
insertBefore()
:把節(jié)點(diǎn)放在childNodes
列表中某個(gè)特定的位置上,這個(gè)方法接受兩個(gè)參數(shù):要插入的節(jié)點(diǎn)和作為參照的節(jié)點(diǎn)筒饰。插入節(jié)點(diǎn)后缴啡,被插入的節(jié)點(diǎn)會(huì)變成參照節(jié)點(diǎn)的前一個(gè)同胞節(jié)點(diǎn)(previousSibling
),同時(shí)被方法返回瓷们。如果參照節(jié)點(diǎn)是null
业栅,則insertBefore()
與appendChild()
執(zhí)行相同的操作秒咐。 -
replaceChild()
:這個(gè)方法接受兩個(gè)參數(shù),要插入的節(jié)點(diǎn)和要替換的節(jié)點(diǎn)碘裕。要替換的節(jié)點(diǎn)將由這個(gè)方法返回并從文檔樹中被移除携取,同時(shí)由要插入的節(jié)點(diǎn)占據(jù)其位置。在使用replaceChild()
插入一個(gè)節(jié)點(diǎn)時(shí)帮孔,該節(jié)點(diǎn)的所有關(guān)系指針都會(huì)從被它替換的節(jié)點(diǎn)復(fù)制過來雷滋。盡管從技術(shù)上講,被替換的節(jié)點(diǎn)仍然還在文檔中文兢,但它在文檔中已經(jīng)沒有了自己的位置晤斩。 -
removeChild()
:這個(gè)方法接受一個(gè)參數(shù),即要移除的節(jié)點(diǎn)姆坚。被移除的節(jié)點(diǎn)將成為方法的返回值澳泵。
-
-
操作節(jié)點(diǎn)的其他方法
-
cloneNode()
,用于創(chuàng)建調(diào)用這個(gè)方法的節(jié)點(diǎn)的一個(gè)完全相同的副本兼呵。cloneNode()
方法接受一個(gè)布爾值參數(shù)兔辅,表示是否執(zhí)行深復(fù)制。在參數(shù)為true
的情況下击喂,執(zhí)行深復(fù)制维苔,也就是復(fù)制節(jié)點(diǎn)及其整個(gè)子節(jié)點(diǎn)樹;在參數(shù)為false
的情況下茫负,執(zhí)行淺復(fù)制蕉鸳,即只復(fù)制節(jié)點(diǎn)本身。復(fù)制后返回的節(jié)點(diǎn)副本屬于文檔所有忍法,但并沒有為它指定父節(jié)點(diǎn)潮尝。因此,這個(gè)節(jié)點(diǎn)副本就成為了一個(gè)“孤兒”饿序,除非通過appendChild()
勉失、insertBefore()
或replaceChild()
將它添加到文檔中。 -
normalize()
原探,由于解析器的實(shí)現(xiàn)或DOM
操作等原因乱凿,可能會(huì)出現(xiàn)文本節(jié)點(diǎn)不包含文本,或者接連出現(xiàn)兩個(gè)文本節(jié)點(diǎn)的情況咽弦。當(dāng)在某個(gè)節(jié)點(diǎn)上調(diào)用這個(gè)方法時(shí)徒蟆,就會(huì)在該節(jié)點(diǎn)的后代節(jié)點(diǎn)中查找上述兩種情況。如果找到了空文本節(jié)點(diǎn)型型,則刪除它段审;如果找到相鄰的文本節(jié)點(diǎn),則將它們合并為一個(gè)文本節(jié)點(diǎn)闹蒜。
-
var deepList = myList.cloneNode(true);
alert(deepList.childNodes.length); //3(IE < 9)或7(其他瀏覽器)
var shallowList = myList.cloneNode(false);
alert(shallowList.childNodes.length); //0
cloneNode()
方法不會(huì)復(fù)制添加到DOM
節(jié)點(diǎn)中的JavaScript
屬性寺枉,例如事件處理程序等抑淫。這個(gè)方法只復(fù)制特性、(在明確指定的情況下也復(fù)制)子節(jié)點(diǎn)姥闪,其他一切都不會(huì)復(fù)制始苇。IE 在此存在一個(gè)bug,即它會(huì)復(fù)制事件處理程序筐喳,所以我們建議在復(fù)制之前最好先移除事件處理程序催式。
二、 Document 類型
document
對(duì)象:在瀏覽器中疏唾,document
對(duì)象是HTMLDocument
(繼承自Document
類型)的一個(gè)實(shí)例蓄氧,表示整個(gè)HTML
頁面。而且槐脏,document
對(duì)象是window
對(duì)象的一個(gè)屬性喉童,因此可以將其作為全局對(duì)象來訪問。通過這個(gè)文檔對(duì)象顿天,不僅可以取得與頁面有關(guān)的信息堂氯,而且還能操作頁面的外觀及其底層結(jié)構(gòu)。Document
節(jié)點(diǎn)具有下列特征: nodeType
的值為9牌废;nodeName
的值為"#document"
咽白;nodeValue
的值為null
; parentNode
的值為null
鸟缕;
document
對(duì)象的屬性
var html = document.documentElement; //取得對(duì)<html>的引用
var body = document.body; //取得對(duì)<body>的引用
var doctype = document.doctype; //取得對(duì)<DOCTYPE>文檔類型的引用
//取得文檔標(biāo)題
var originalTitle = document.title;
//設(shè)置文檔標(biāo)題
document.title = "New page title";
//取得完整的URL晶框,不可設(shè)置
var url = document.URL;
//取得域名,可設(shè)置懂从,但是不能隨便設(shè)置
var domain = document.domain;
//假設(shè)頁面來自p2p.wrox.com 域
document.domain = "wrox.com"; // 成功
document.domain = "nczonline.net"; // 出錯(cuò)授段! 只能省略域名
//取得來源頁面的URL,不可設(shè)置
var referrer = document.referrer;
查找元素
1番甩、getElementById()
:接收一個(gè)參數(shù):要取得的元素的ID
侵贵。如果找到相應(yīng)的元素則返回該元素,如果不存在帶有相應(yīng)ID 的元素缘薛,則返回null
窍育。注意,這里的ID
必須與頁面中元素的id
特性(attribute
)嚴(yán)格匹配宴胧,包括大小寫漱抓。IE8 及較低版本不區(qū)分ID
的大小寫,因此"myDiv"
和"mydiv"
會(huì)被當(dāng)作相同的元素ID
恕齐。如果頁面中多個(gè)元素的ID 值相同辽旋,getElementById()
只返回文檔中第一次出現(xiàn)的元素。
<input type="text" name="myElement" value="Text field">
<div id="myElement">A div</div>
基于這段HTML 代碼,在IE7 中調(diào)用document.getElementById("myElement ")
补胚,結(jié)果會(huì)返回<input>
元素;而在其他所有瀏覽器中追迟,都會(huì)返回對(duì)<div>
元素的引用溶其。為了避免IE中存在的這個(gè)問題,最好的辦法是不讓表單(<input>
敦间、<textarea>
瓶逃、<button>
及<select>
)字段的name
特性與其他元素的ID
相同。
2廓块、getElementsByTagName()
厢绝。這個(gè)方法接受一個(gè)參數(shù),即要取得元素的標(biāo)簽名带猴,返回一個(gè)HTMLCollection
對(duì)象昔汉,作為一個(gè)“動(dòng)態(tài)”集合,返回所有的標(biāo)簽元素組成的類數(shù)組拴清。HTMLCollection
對(duì)象還有一個(gè)方法靶病,叫做namedItem()
,使用這個(gè)方法可以通過元素的name
特性取得集合中的項(xiàng)口予。例如娄周,
<img src="myimage.gif" name="myImage">
// 那么就可以通過如下方式從images幾個(gè)中取得對(duì)應(yīng)name的<img>元素:
var images = document.getElementsByTagName("img");
var myImage = images.namedItem("myImage");
// HTMLCollection 還支持按名稱訪問項(xiàng)
var myImage = images["myImage"];
在通過元素調(diào)用這個(gè)方法時(shí),除了搜索起點(diǎn)是當(dāng)前元素之外沪停,其他方面都跟通過
document
調(diào)用這個(gè)方法相同煤辨,因此結(jié)果只會(huì)返回當(dāng)前元素的后代。
var ul = document.getElementById("myList");
var items = ul.getElementsByTagName("li");
3木张、getElementsByClassName()
:這個(gè)方法接受一個(gè)參數(shù)众辨,即要取得元素的類名,返回一個(gè)HTMLCollection
對(duì)象窟哺,作為一個(gè)“動(dòng)態(tài)”集合泻轰,返回所有擁有該類的元素組成的類數(shù)組且轨。
4浮声、為訪問文檔常用的部分提供了快捷方式:
-
document.anchors
旋奢,包含文檔中所有帶name
特性的<a>
元素; -
document.forms
矗钟,包含文檔中所有的<form>
元素 -
document.images
,包含文檔中所有的<img>
元素 -
document.links
躬它,包含文檔中所有帶href 特性的<a>
元素。
這些特殊集合始終都可以通過HTMLDocument
對(duì)象訪問到东涡,而且冯吓,與HTMLCollection
對(duì)象類似,集合中的項(xiàng)也會(huì)隨著當(dāng)前文檔內(nèi)容的更新而更新疮跑。
文檔寫入
write()
和writeln()
方法都接受一個(gè)字符串參數(shù)组贺,即要寫入到輸出流中的文本。write()
會(huì)原樣寫入祖娘,而writeln()
則會(huì)在字符串的末尾添加一個(gè)換行符(\n
)失尖。在頁面被加載的過程中,可以使用這兩個(gè)方法向頁面中動(dòng)態(tài)地加入內(nèi)容贿条。方法open()
和close()
分別用于打開和關(guān)閉網(wǎng)頁的輸出流雹仿。
<html>
<head>
<title>document.write() Example</title>
</head>
<body>
<p>The current date and time is:
<script type="text/javascript">
document.write("<strong>" + (new Date()).toString() + "</strong>");
</script>
</p>
</body>
</html>
這樣做會(huì)創(chuàng)建一個(gè)DOM
元素,而且可以在將來訪問該元素整以。通過write()
和writeln()
輸出的任何HTML
代碼都將如此處理胧辽。
還可以使用write()
和writeln()
方法動(dòng)態(tài)地包含外部資源,例如JavaScript
文件等公黑。在包含JavaScript
文件時(shí)邑商,必須注意不能像下面的例子那樣直接包含字符串"</script>"
,因?yàn)檫@會(huì)導(dǎo)致該字符串被解釋為腳本塊的結(jié)束凡蚜,它后面的代碼將無法執(zhí)行人断。應(yīng)該使用轉(zhuǎn)義符做處理"<\/script>"
window.onload
事件處理程序,等到頁面完全加載之后延遲執(zhí)行函數(shù)朝蜘。函數(shù)執(zhí)行之后恶迈,調(diào)用document.write()
會(huì)重寫整個(gè)頁面內(nèi)容。
三谱醇、Element 類型
Element
類型用于表現(xiàn)XML
或HTML
元素暇仲,提供了對(duì)元素標(biāo)簽名、子節(jié)點(diǎn)及特性的訪問副渴。Element
節(jié)點(diǎn)具有以下特征:nodeType
的值為1奈附;nodeName
的值為元素的標(biāo)簽名;nodeValue
的值為null
煮剧;
要訪問元素的標(biāo)簽名斥滤,可以使用nodeName
屬性将鸵,也可以使用tagName
屬性;這兩個(gè)屬性會(huì)返回相同的值佑颇。
所有HTML
元素都由HTMLElement
類型表示顶掉,不是直接通過這個(gè)類型,也是通過它的子類型來表示漩符。HTMLElement
類型直接繼承自Element
并添加了一些屬性一喘。添加的這些屬性分別對(duì)應(yīng)于每個(gè)HTML元素中都存在的下列標(biāo)準(zhǔn)特性。
id嗜暴,元素在文檔中的唯一標(biāo)識(shí)符
title,有關(guān)元素的附加說明信息
lang议蟆,元素內(nèi)容的語言代碼闷沥,很少使用。
dir咐容,語言的方向舆逃,值有l(wèi)tr從左到右 rtl從右到做 ,很少使用
className戳粒,與元素的class 特性對(duì)應(yīng)路狮,即為元素指定的CSS類。
沒有將這個(gè)屬性命名為class蔚约,是因?yàn)閏lass 是ECMAScript 的保留字奄妨。
通過className訪問而不是class,**但是在使用操作元素屬性的方法時(shí)需要使用class苹祟,與html上的屬性保持一致**
<div id="myDiv" class="bd" title="Body text" lang="en" dir="ltr"></div>
操作元素屬性
每個(gè)元素都有一或多個(gè)特性砸抛,這些特性的用途是給出相應(yīng)元素或其內(nèi)容的附加信息。操作特性的DOM
方法主要有三個(gè)树枫,分別是getAttribute()
直焙、setAttribute()
和removeAttribute()
,接受特性字符串作為第一個(gè)參數(shù)砂轻。setAttribute()
可以傳第二個(gè)參數(shù)作為設(shè)置的新值奔誓。特性的名稱是不區(qū)分大小寫的,即"ID"
和"id"
代表的都是同一個(gè)特性搔涝。另外也要注意厨喂,根據(jù)HTML5
規(guī)范,自定義特性應(yīng)該加上data-
前綴以便驗(yàn)證体谒。
注意杯聚,傳遞給
getAttribute()
的特性名與實(shí)際的特性名相同。因此要想得到class
特性值抒痒,應(yīng)該傳入"class"
而不是"className"
幌绍,后者只有在通過對(duì)象屬性訪問特性時(shí)才用。如果給定名稱的特性不存在,getAttribute()
返回null
傀广。
1颁独、 getAttribute()
獲取屬性
任何元素的所有特性,也都可以通過DOM
元素本身的屬性來訪問伪冰。不過誓酒,只有公認(rèn)的(非自定義的)特性才會(huì)以屬性的形式添加到DOM
對(duì)象中。自定義屬性只能通過getAttribute()
來獲得
<div id="myDiv" align="left" my_special_attribute="hello!"></div>
alert(div.id); //"myDiv"
alert(div.my_special_attribute); //undefined(IE 除外)
alert(div.align); //"left"
有兩類特殊的特性贮聂,它們雖然有對(duì)應(yīng)的屬性名靠柑,但屬性的值與通過getAttribute()
返回的值并不相同。
-
第一類特性就是style吓懈,用于通過CSS 為元素指定樣式歼冰。
- 在通過
getAttribute()
訪問時(shí),返回的style
特性值中包含的是CSS
文本 - 而通過屬性來訪問它則會(huì)返回一個(gè)對(duì)象耻警。由于
style
屬性是用于以編程方式訪問元素樣式的(本章后面討論)隔嫡,因此并沒有直接映射到style
特性。
- 在通過
-
第二類與眾不同的特性是
onclick
這樣的事件處理程序甘穿。- 如果通過
getAttribute()
訪問腮恩,則會(huì)返回相應(yīng)代碼的字符串。 - 在訪問
onclick
屬性時(shí)温兼,則會(huì)返回一個(gè)JavaScript
函數(shù)(如果未在元素中指定相應(yīng)特性秸滴,則返回null
)。這是因?yàn)?code>onclick及其他事件處理程序?qū)傩员旧砭蛻?yīng)該被賦予函數(shù)值妨托。
- 如果通過
由于存在這些差別缸榛,在通過
JavaScript
以編程方式操作DOM
時(shí),開發(fā)人員經(jīng)常不使用getAttribute()
兰伤,而是只使用對(duì)象的屬性内颗。只有在取得自定義特性值的情況下,才會(huì)使用getAttribute()
方法敦腔。
2均澳、 setAttribute()
獲取屬性
setAttribute()
,這個(gè)方法接受兩個(gè)參數(shù):要設(shè)置的特性名和值符衔。如果特性已經(jīng)存在找前,setAttribute()
會(huì)以指定的值替換現(xiàn)有的值;如果特性不存在判族,setAttribute()
則創(chuàng)建該屬性并設(shè)置相應(yīng)的值躺盛。通過setAttribute()
方法既可以操作HTML
特性也可以操作自定義特性。通過這個(gè)方法設(shè)置的特性名會(huì)被統(tǒng)一轉(zhuǎn)換為小寫形式形帮,即"ID"最終會(huì)變成"id"槽惫。如果是使用這樣的方式oDiv.myColor="div1"
的方式設(shè)置的自定義屬性周叮,用getAttribute()
是訪問不到的。
3界斜、 removeAttribute()
刪除屬性
接受一個(gè)參數(shù)仿耽,即刪除的屬性key,這個(gè)方法用于徹底刪除元素的特性各薇。調(diào)用這個(gè)方法不僅會(huì)清除特性的值项贺,而且也會(huì)從元素中完全刪除特性,oDiv.removeAttribute("class");
創(chuàng)建元素
1峭判、 document.createElement()
創(chuàng)建元素
這個(gè)方法只接受一個(gè)參數(shù)开缎,即要?jiǎng)?chuàng)建元素的標(biāo)簽名(IE中可以傳入完整的HTML標(biāo)簽字符串)。這個(gè)標(biāo)簽名在HTML
文檔中不區(qū)分大小寫林螃,而在XML
(包括XHTML
)文檔中啥箭,則是區(qū)分大小寫的。
var oDiv = document.createElement("div");
2治宣、 增加元素
-
appendChild()
:ParentElement.appendChild(element);
在父元素末尾添加一個(gè)子元素 -
insertBefore()
:ParentElement.insertBefore(newElement,refElement);
指定的已有子節(jié)點(diǎn)之前插入新的子節(jié)點(diǎn)。
3砌滞、刪除元素
-
removeChild()
:ParentElement.removeChild(elelment);
在父元素中移除某個(gè)子元素
4侮邀、改變?cè)?/strong>
-
replaceChild()
:ParentElement.replaceChild(newElement,oldElement);
在父元素中替換某個(gè)子元素
元素的子節(jié)點(diǎn)
元素的childNodes
屬性中包含了它的所有子節(jié)點(diǎn),這些子節(jié)點(diǎn)有可能是元素贝润、文本節(jié)點(diǎn)绊茧、注釋或處理指令。IE會(huì)返回所有的子元素節(jié)點(diǎn)打掘,而其他瀏覽器則返回所有的子節(jié)點(diǎn)华畏,這意味著在執(zhí)行某項(xiàng)操作以前,通常都要先檢查一下nodeTpye
屬性
for (var i=0, len=element.childNodes.length; i < len; i++){
if (element.childNodes[i].nodeType == 1){
//對(duì)子元素節(jié)點(diǎn)執(zhí)行某些操作
}
}
四尊蚁、Text 類型
每個(gè)可以包含內(nèi)容的元素最多只能有一個(gè)文本節(jié)點(diǎn)亡笑,而且必須確實(shí)有內(nèi)容存在。(只有空格也算是有內(nèi)容)
-
nodeType
的值為3
横朋; -
nodeName
的值為"#text"
仑乌; -
nodeValue
的值為節(jié)點(diǎn)所包含的文本;
如果這個(gè)文本節(jié)點(diǎn)當(dāng)前存在于文檔樹中琴锭,那么修改文本節(jié)點(diǎn)的結(jié)果就會(huì)立即得到反映晰甚。另外,在修改文本節(jié)點(diǎn)時(shí)還要注意决帖,此時(shí)的字符串會(huì)經(jīng)過HTML
(或XML
厕九,取決于文檔類型)編碼。換句話說地回,小于號(hào)扁远、大于號(hào)或引號(hào)都會(huì)像下面的例子一樣被轉(zhuǎn)義俊鱼。
Some <strong>other</strong> message
轉(zhuǎn)義為
Some <strong>other</strong> message
創(chuàng)建文本節(jié)點(diǎn)
document.createTextNode()
: 創(chuàng)建新文本節(jié)點(diǎn),這個(gè)方法接受一個(gè)參數(shù)——要插入節(jié)點(diǎn)中的文本穿香。與設(shè)置已有文本節(jié)點(diǎn)的值一樣亭引,作為參數(shù)的文本也將按照HTML
或XML
的格式進(jìn)行編碼。創(chuàng)建的文本節(jié)點(diǎn)皮获,可以使用元素的appendChild()
將其添加到元素中焙蚓,在沒有添加進(jìn)DOM樹之前,都是屬于孤兒節(jié)點(diǎn)洒宝,文檔碎片购公。
var textNode = document.createTextNode("Hello world!");
element.appendChild(textNode);
一般情況下,每個(gè)元素只有一個(gè)文本子節(jié)點(diǎn)雁歌。不過宏浩,在某些情況下也可能包含多個(gè)文本子節(jié)點(diǎn),比如使用appendChild()
方法多次添加文本節(jié)點(diǎn)靠瞎,那么這兩個(gè)節(jié)點(diǎn)中的文本就會(huì)連起來顯示比庄,中間不會(huì)有空格。如果在一個(gè)包含兩個(gè)或多個(gè)文本節(jié)點(diǎn)的父元素上調(diào)用normalize()
方法乏盐,則會(huì)將所有文本節(jié)點(diǎn)合并成一個(gè)節(jié)點(diǎn)佳窑,結(jié)果節(jié)點(diǎn)的nodeValue
等于將合并前每個(gè)文本節(jié)點(diǎn)的nodeValue
值拼接起來的值。
瀏覽器在解析文檔時(shí)永遠(yuǎn)不會(huì)創(chuàng)建相鄰的文本節(jié)點(diǎn)父能。這種情況只會(huì)作為執(zhí)行DOM操作的結(jié)果出現(xiàn)神凑。
五、DOM操作技術(shù)
DOM
操作往往是JavaScript
程序中開銷最大的部分何吝,而因訪問NodeList
導(dǎo)致的問題最多溉委。NodeList
對(duì)象都是“動(dòng)態(tài)的”,這就意味著每次訪問NodeList
對(duì)象爱榕,都會(huì)運(yùn)行一次查詢瓣喊。有鑒于此,最好的辦法就是盡量減少DOM
操作呆细。
動(dòng)態(tài)腳本
指的是在頁面加載時(shí)不存在型宝,但將來的某一時(shí)刻通過修改DOM動(dòng)態(tài)添加的腳本。
1絮爷、插入外部文件
function loadScript(url){
var script = document.createElement("script");
script.type = "text/javascript";
script.src = url;
document.body.appendChild(script); // 在這行代碼執(zhí)行之前都不會(huì)下載文件
}
loadScript("client.js"); // 方法調(diào)用時(shí) 動(dòng)態(tài)添加script標(biāo)簽 并執(zhí)行腳本
2趴酣、行內(nèi)方式,也是添加script標(biāo)簽 坑夯,但是腳本代碼吧不是從外部引入岖寞,而是本地添加進(jìn)去。所有寫在<script></script>標(biāo)簽對(duì)中的代碼都算是script元素的文本節(jié)點(diǎn)
var script = document.createElement("script");
script.type = "text/javascript";
script.text = "function sayHi(){alert('hi');}";
document.body.appendChild(script);
Safari 3.0 之前的版本不能正確地支持text
屬性柜蜈,可以使用創(chuàng)建文本節(jié)點(diǎn)的方式解決仗谆。
function loadScriptString(code){
var script = document.createElement("script");
script.type = "text/javascript";
try {
script.appendChild(document.createTextNode(code));
} catch (ex){
script.text = code;
}
document.body.appendChild(script);
}
loadScriptString("function sayHi(){alert('hi');}");
動(dòng)態(tài)樣式
能夠把CSS 樣式包含到HTML 頁面中的元素有兩個(gè)指巡。其中,<link>
元素用于包含來自外部的文件隶垮,而<style>
元素用于指定嵌入的樣式藻雪。
同理。操作DOM
代碼添加標(biāo)簽可以很容易地動(dòng)態(tài)創(chuàng)建出作用CSS樣式的元素:
1狸吞、外部引入link
function loadStyles(url){
var link = document.createElement("link");
link.rel = "stylesheet";
link.type = "text/css";
link.href = url;
var head = document.getElementsByTagName("head")[0];
head.appendChild(link);
}
loadStyles("myStyle.css");
加載外部樣式文件的過程是異步的勉耀,也就是加載樣式與執(zhí)行JavaScript
代碼的過程沒有固定的次序。
2蹋偏、內(nèi)部style
這種方式會(huì)實(shí)時(shí)地向頁面中添加樣式便斥,因此能夠馬上看到變化。
function loadStyleString(css){
var style = document.createElement("style");
style.type = "text/css";
try{
style.appendChild(document.createTextNode(css));
} catch (ex){
style.styleSheet.cssText = css;
}
var head = document.getElementsByTagName("head")[0];
head.appendChild(style);
}
loadStyleString("body{background-color:red}");
事實(shí)上威始,IE 此時(shí)拋出的錯(cuò)誤(將<script>
枢纠、<style>
視為一個(gè)特殊的元素,不允許DOM
訪問其子節(jié)點(diǎn)黎棠。)晋渺。解決IE 中這個(gè)問題的辦法,就是訪問元素的styleSheet
屬性脓斩,該屬性又有一個(gè)cssText
屬性些举,可以接受CSS
代碼
操作表格
為了方便構(gòu)建表格,HTML DOM
還為<table>
俭厚、<tbody>
和<tr>
元素添加了一些屬性和方法。
為<table>
元素添加的屬性和方法如下驶臊。
-
caption
:保存著對(duì)<caption>
元素(如果有)的指針挪挤。 -
tBodies
:是一個(gè)<tbody>
元素的HTMLCollection
。 -
tFoot
:保存著對(duì)<tfoot>
元素(如果有)的指針关翎。 -
tHead
:保存著對(duì)<thead>
元素(如果有)的指針扛门。 -
rows
:是一個(gè)表格中所有行的HTMLCollection
。 -
createTHead()
:創(chuàng)建<thead>
元素纵寝,將其放到表格中论寨,返回引用。 -
createTFoot()
:創(chuàng)建<tfoot>
元素爽茴,將其放到表格中葬凳,返回引用。 -
createCaption()
:創(chuàng)建<caption>
元素室奏,將其放到表格中火焰,返回引用。 -
deleteTHead()
:刪除<thead>
元素胧沫。 -
deleteTFoot()
:刪除<tfoot>
元素昌简。 -
deleteCaption()
:刪除<caption>
元素占业。 -
deleteRow(pos)
:刪除指定位置的行。 -
insertRow(pos)
:向rows 集合中的指定位置插入一行纯赎。
為<tbody>
元素添加的屬性和方法如下谦疾。
-
rows
:保存著<tbody>
元素中行的HTMLCollection
。 -
deleteRow(pos)
:刪除指定位置的行犬金。 -
insertRow(pos)
:向rows
集合中的指定位置插入一行念恍,返回對(duì)新插入行的引用。
為<tr>
元素添加的屬性和方法如下佑附。
-
cells
:保存著<tr>
元素中單元格的HTMLCollection
樊诺。 -
deleteCell(pos)
:刪除指定位置的單元格。 -
insertCell(pos)
:向cells
集合中的指定位置插入一個(gè)單元格音同,返回對(duì)新插入單元格的引用词爬。
使用NodeList
理解NodeList
及其“近親”NamedNodeMap
和HTMLCollection
,是從整體上透徹理解DOM
的關(guān)鍵所在权均。這三個(gè)集合都是“動(dòng)態(tài)的”顿膨;換句話說,每當(dāng)文檔結(jié)構(gòu)發(fā)生變化時(shí)叽赊,它們都會(huì)得到更新恋沃。因此,它們始終都會(huì)保存著最新必指、最準(zhǔn)確的信息囊咏。從本質(zhì)上說,所有NodeList
對(duì)象都是在訪問DOM
文檔時(shí)實(shí)時(shí)運(yùn)行的查詢塔橡。
如果想要迭代一個(gè)NodeList
梅割,最好是使用length
屬性初始化第二個(gè)變量,然后將迭代器與該變量進(jìn)行比較葛家。因?yàn)?code>NodeList是動(dòng)態(tài)的户辞,NodeList.length
也是動(dòng)態(tài)的,如果在迭代的過程對(duì)這個(gè)NodeList
有添加Node
的操作癞谒,將會(huì)無限迭代下去底燎,所以可以使用變量暫存length:var len = NodeList.length
一般來說,應(yīng)該盡量減少訪問NodeList
的次數(shù)弹砚。因?yàn)槊看卧L問NodeList
双仍,都會(huì)運(yùn)行一次基于文檔的查詢。所以桌吃,可以考慮將從NodeList
中取得的值緩存起來殊校。