十八

DOM2和DOM3
DOM1級(jí)主要定義的是HTML和XML文檔的低層結(jié)構(gòu)。DOM2和DOM3級(jí)則在這個(gè)結(jié)構(gòu)的基礎(chǔ)上引入了更多的交互能力,也支持了更高級(jí)的XML特性。

針對(duì)XML命名空間的變化
有了XML命名空間,不同XML文檔的元素就可以混合在一起,共同構(gòu)成格式良好的文檔,而不必?fù)?dān)心發(fā)生命名沖突。從技術(shù)上來(lái)說(shuō),HTML不支持XML命名空間,但XHTML支持XML命名空間。

<xhtml:html xmlns:xhtml="http://www.w3.org/1999/xhtml">
    <xhtml:head>
        <xhtml:title>Example XHTML page</xhtml:title>
     </xhtml:head>
     <xhtml:body>
           Hello world!
     </xhtml:body>
</xhtml:html>

2、Document類(lèi)型的變化
3、Element類(lèi)型的變化
4、NamedNodeMap類(lèi)型的變化
5、框架的變化
框架和內(nèi)嵌框架分別用HTMLFrameElement和HTMLIFrameElement表示,它們?cè)贒OM2級(jí)中都有了一個(gè)新屬性,名叫contentDocument。

var iframe = document.getElementById("myIframe");
var iframeDoc = iframe.contentDocument;//IE8前無(wú)效

IE8之前不支持框架中的contentDocument屬性,但支持一個(gè)名叫contentWindow的屬性。

var iframe = document.getElementById("myIframe");
var iframeDoc = iframe.contentDocument || iframe.contentWindow.document;

關(guān)于DOM2和DOM3其他內(nèi)容省略

事件
JavaScript與HTML之間的交互是通過(guò)事件實(shí)現(xiàn)的。事件流描述的是從頁(yè)面中接收事件的順序。但有意思的是,IE和Netscape開(kāi)發(fā)團(tuán)隊(duì)居然提出了超不多是完全相反的事件流的概念。IE的事件流是事件冒泡流,而Netscape Communicator的事件流是事件捕獲流。

事件冒泡
IE的事件流叫做事件冒泡,即事件開(kāi)始時(shí)由最具體的元素(文檔中嵌套層次最深的那個(gè)節(jié)點(diǎn))接收,然后逐級(jí)向上傳播到較為不具體的節(jié)點(diǎn)(文檔):

<!DOCTYPE html>
<html>
<head>
    <title>Event Bubbling Example</title>
</head>
<body>
    <div id="myDiv">Click Me</div>
</body>
</html>

如果你單擊了頁(yè)面中的<div>元素,那么這個(gè)click事件會(huì)按照如下順序傳播:

(1) <div>
(2) <body>
(3) <html>
(4) document

也就是說(shuō),click事件首先在<div>元素上發(fā)生,而這個(gè)元素就是我們單擊的元素。然后,click事件沿DOM樹(shù)向上傳播,在每一級(jí)節(jié)點(diǎn)上都會(huì)發(fā)生,直至傳播到document對(duì)象。
所有現(xiàn)代瀏覽器都支持事件冒泡,但在具體實(shí)現(xiàn)上還是有一些差別。IE5.5及更早版本中的事件冒泡會(huì)跳過(guò)<html>元素(從<body>直接跳到document)。IE9、Firefox、Chrome和Safari則將事件一直冒泡到window對(duì)象。

事件捕獲
Netscape Communicator團(tuán)隊(duì)提出的另一種事件流叫做事件捕獲。事件捕獲的思想是不太具體的節(jié)點(diǎn)應(yīng)該更早接受到事件,而最具體的節(jié)點(diǎn)應(yīng)該最后接收到事件。事件捕獲的用意在于在事件到達(dá)預(yù)定目標(biāo)之前捕獲它:

(1) document
(2) <html>
(3) <body>
(4) <div>

在事件捕獲過(guò)程中,document對(duì)象首先接收到click事件,然后事件沿DOM樹(shù)依次向下,一直傳播到事件的實(shí)際目標(biāo),即<div>元素。
雖然事件捕獲是Netscape Communicator唯一支持的事件流模型,但I(xiàn)E9、Safari、Chrome、Opera和Firefox目前也都支持這種事件流模型。盡管“DOM2級(jí)事件”規(guī)范要求事件應(yīng)該從document對(duì)象開(kāi)始傳播,但這些瀏覽器都是從window對(duì)象開(kāi)始捕獲事件的。由于老版本的瀏覽器不支持,因此很少有人使用事件捕獲。我們也建議讀者放心地使用事件冒泡,在有特殊需要時(shí)再使用事件捕獲。

DOM事件流
“DOM2級(jí)事件”規(guī)定的事件流包含三個(gè)階段:事件捕獲階段、處于目標(biāo)階段和事件冒泡階段。首先發(fā)生的是事件捕獲,為截獲事件提供了機(jī)會(huì)。然后是實(shí)際的目標(biāo)接受到事件。最后一個(gè)階段是冒泡階段,可以在這個(gè)階段對(duì)事件作出響應(yīng):


在DOM事件流中,實(shí)際的目標(biāo)(<div>元素)在捕獲階段不會(huì)接收到事件。這意味著在捕獲階段,事件從document到<html>再到<body>后就停止了。下一個(gè)階段是“處于目標(biāo)”階段,于是事件在<div>上發(fā)生,并在事件處理中被看成冒泡階段的一個(gè)部分。然后,冒泡階段發(fā)生事件又傳播回文檔。
多數(shù)支持DOM事件流的瀏覽器都實(shí)現(xiàn)了一種特定的行為;即使“DOM2級(jí)事件”規(guī)范明確要求捕獲階段不會(huì)涉及事件目標(biāo),但I(xiàn)E9、Safari、Chrome、Firefox和Opera9.5及更高版本都會(huì)在捕獲階段觸發(fā)事件對(duì)象上的事件。結(jié)果,就是有兩個(gè)機(jī)會(huì)在目標(biāo)對(duì)象上面操作事件。

IE9、Opera、Firefox、Chrome 、 Safari都支持DOM事件流;IE8及更早版本不支持DOM事件流。

事件處理程序
響應(yīng)某個(gè)事件的函數(shù)就叫做事件處理程序(或事件偵聽(tīng)器)。

DOM0級(jí)事件處理程序

var btn = document.getElementById("myBtn");
btn.onclick = function(){
    alert("Clicked");
};
btn.onclick = null; //刪除事件處理程序

DOM2級(jí)事件處理程序
“DOM2級(jí)事件”定義了兩個(gè)方法,用于處理指定和刪除事件處理程序的操作:addEventListener()和removeEventListener()。所有DOM節(jié)點(diǎn)中都包含這兩個(gè)方法,并且它們都接受3個(gè)參數(shù):要處理的事件名、作為事件處理程序的函數(shù)和一個(gè)布爾值。最后這個(gè)布爾值參數(shù)如果是true,表示在捕獲階段調(diào)用事件處理程序;如果是false,表示在冒泡階段調(diào)用事件處理程序。
要在按鈕上為click事件添加事件處理程序:

var btn = document.getElementById("myBtn");
btn.addEventListener("click", function() {
    alert(this.id);
}, false);

該事件會(huì)在冒泡階段被觸發(fā)(因?yàn)樽詈笠粋€(gè)參數(shù)是false)。使用DOM2級(jí)方法添加事件處理程序的主要好處是可以添加多個(gè)事件處理程序:

var btn = document.getElementById("myBtn");
btn.addEventListener("click", function() {
    alert(this.id);
}, false);
btn.addEventListener("click", function() {
    alert("Hello world!");
}, false);

通過(guò)addEventListener()添加的事件處理程序只能使用removeEventListener()來(lái)移除;移除時(shí)傳入的參數(shù)與添加處理程序時(shí)使用的參數(shù)相同。這也意味著通過(guò)addEventListener()添加的匿名函數(shù)將無(wú)法移除:

var btn = document.getElementById("myBtn");
btn.addEventListener("click", function() {
    alert(this.id);
}, false);
//這里省略了其他代碼
btn.removeEventListener("click", function() { //沒(méi)有用!
    alert(this.id);
}, false);
var btn = document.getElementById("myBtn");
var handler = function() {
    alert(this.id);
};
btn.addEventListener("click", handler, false);
//這里省略了其他代碼
btn.removeEventListener("click", handler, false); //有效!

大多數(shù)情況下,都是將事件處理程序添加到事件流的冒泡階段,這樣可以最大限度地兼容各種瀏覽器。最好只在需要在事件到達(dá)目標(biāo)之前捕獲它的時(shí)候?qū)⑹录幚沓绦蛱砑拥讲东@階段。如果不是特別需要,我們不建議在事件捕獲階段注冊(cè)事件處理程序。

IE9??Firefox??Safari??Chrome ?? Opera支持DOM2級(jí)事件處理程序。

IE事件處理程序
IE實(shí)現(xiàn)了與DOM中類(lèi)似的兩個(gè)方法:attachEvent()和detachEvent()。這兩個(gè)方法接受相同的兩個(gè)參數(shù):事件處理程序名稱(chēng)和事件處理程序函數(shù)。由于IE8及更早版本只支持事件冒泡,所以通過(guò)attachEvent()添加的事件處理程序都會(huì)被添加到冒泡階段。

var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function() {
    alert("Clicked");
});

在IE中使用attachEvent()與使用DOM0級(jí)方法的主要區(qū)別在于事件處理程序的作用域。在使用DOM0級(jí)方法的情況下,事件處理程序會(huì)在其所屬元素的作用域內(nèi)運(yùn)行;在使用attachEvent()方法的情況下,事件處理程序會(huì)在全局作用域中運(yùn)行,因此this等于window:

var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function() {
    alert(this === window); //true
});

與addEventListener()類(lèi)似,attachEvent()方法也可以用來(lái)為一個(gè)元素添加多個(gè)事件處理程序:

var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function() {
    alert("Clicked");
});
btn.attachEvent("onclick", function() {
    alert("Hello world!");
});

不過(guò),與DOM方法不同的是,這些事件處理程序不是以添加它們的順序執(zhí)行,而以相反的順序被觸發(fā)(IE8下)。單擊這個(gè)例子中的按鈕,首先看到的是“Hello world!”,然后才是“Clicked”。
使用attachEvent()添加的事件可以通過(guò)detachEvent()來(lái)移除,條件是必須提供相同的參數(shù),與DOM方法一樣,這也意味著添加的匿名函數(shù)將不能移除:

var btn = document.getElementById("myBtn");
var handler = function() {
    alert("Clicked");
};
btn.attachEvent("onclick", handler);
//這里省略了其他代碼
btn.detachEvent("onclick", handler);

支持IE事件處理程序的瀏覽器有IE和Opera。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • ??JavaScript 與 HTML 之間的交互是通過(guò)事件實(shí)現(xiàn)的。 ??事件,就是文檔或?yàn)g覽器窗口中發(fā)生的一些特...
    霜天曉閱讀 3,701評(píng)論 1 11
  • JavaScript 程序采用了異步事件驅(qū)動(dòng)編程模型。在這種程序設(shè)計(jì)風(fēng)格下,當(dāng)文檔、瀏覽器、元素或與之相關(guān)的對(duì)象發(fā)...
    劼哥stone閱讀 1,333評(píng)論 3 11
  • JavaScript 與 HTML 之間的交互是通過(guò)事件實(shí)現(xiàn)的。事件,就是文檔或?yàn)g覽器窗口中發(fā)生的一些特定的交互瞬...
    threetowns閱讀 414評(píng)論 0 0
  • 事件流 JavaScript與HTML之間的交互是通過(guò)事件實(shí)現(xiàn)的。事件,就是文檔或?yàn)g覽器窗口中發(fā)生的一些特定的交互...
    DHFE閱讀 914評(píng)論 0 3
  • js之事件機(jī)制 1、事件初探 1.1 js事件的概述 JavaScript事件:JavaScript是基于事件驅(qū)動(dòng)...
    道無(wú)虛閱讀 2,632評(píng)論 0 2

友情鏈接更多精彩內(nèi)容