DOM2和DOM3
DOM1级主要定义的是HTML和XML文档的低层结构。DOM2和DOM3级则在这个结构的基础上引入了更多的交互能力,也支持了更高级的XML特性。
针对XML命名空间的变化
有了XML命名空间,不同XML文档的元素就可以混合在一起,共同构成格式良好的文档,而不必担心发生命名冲突。从技术上来说,HTML不支持XML命名空间,但XHTML支持XML命名空间。
Example XHTML page
Hello world!
2、Document类型的变化
3、Element类型的变化
4、NamedNodeMap类型的变化
5、框架的变化
框架和内嵌框架分别用HTMLFrameElement和HTMLIFrameElement表示,它们在DOM2级中都有了一个新属性,名叫contentDocument。
var iframe = document.getElementById("myIframe");
var iframeDoc = iframe.contentDocument;//IE8前无效
IE8之前不支持框架中的contentDocument属性,但支持一个名叫contentWindow的属性。
var iframe = document.getElementById("myIframe");
var iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
关于DOM2和DOM3其他内容省略
事件
JavaScript与HTML之间的交互是通过事件实现的。事件流描述的是从页面中接收事件的顺序。但有意思的是,IE和Netscape开发团队居然提出了超不多是完全相反的事件流的概念。IE的事件流是事件冒泡流,而Netscape Communicator的事件流是事件捕获流。
事件冒泡
IE的事件流叫做事件冒泡,即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档):
Event Bubbling Example
Click Me
如果你单击了页面中的
(1)
(2)
(3)
(4) document
也就是说,click事件首先在
元素上发生,而这个元素就是我们单击的元素。然后,click事件沿DOM树向上传播,在每一级节点上都会发生,直至传播到document对象。
所有现代浏览器都支持事件冒泡,但在具体实现上还是有一些差别。IE5.5及更早版本中的事件冒泡会跳过元素(从直接跳到document)。IE9、Firefox、Chrome和Safari则将事件一直冒泡到window对象。
事件捕获
Netscape Communicator团队提出的另一种事件流叫做事件捕获。事件捕获的思想是不太具体的节点应该更早接受到事件,而最具体的节点应该最后接收到事件。事件捕获的用意在于在事件到达预定目标之前捕获它:
(1) document
(2)
(3)
(4)
在事件捕获过程中,document对象首先接收到click事件,然后事件沿DOM树依次向下,一直传播到事件的实际目标,即
元素。
虽然事件捕获是Netscape Communicator唯一支持的事件流模型,但IE9、Safari、Chrome、Opera和Firefox目前也都支持这种事件流模型。尽管“DOM2级事件”规范要求事件应该从document对象开始传播,但这些浏览器都是从window对象开始捕获事件的。由于老版本的浏览器不支持,因此很少有人使用事件捕获。我们也建议读者放心地使用事件冒泡,在有特殊需要时再使用事件捕获。
DOM事件流
“DOM2级事件”规定的事件流包含三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段。首先发生的是事件捕获,为截获事件提供了机会。然后是实际的目标接受到事件。最后一个阶段是冒泡阶段,可以在这个阶段对事件作出响应:
在DOM事件流中,实际的目标(元素)在捕获阶段不会接收到事件。这意味着在捕获阶段,事件从document到再到后就停止了。下一个阶段是“处于目标”阶段,于是事件在上发生,并在事件处理中被看成冒泡阶段的一个部分。然后,冒泡阶段发生事件又传播回文档。
多数支持DOM事件流的浏览器都实现了一种特定的行为;即使“DOM2级事件”规范明确要求捕获阶段不会涉及事件目标,但IE9、Safari、Chrome、Firefox和Opera9.5及更高版本都会在捕获阶段触发事件对象上的事件。结果,就是有两个机会在目标对象上面操作事件。
IE9、Opera、Firefox、Chrome 、 Safari都支持DOM事件流;IE8及更早版本不支持DOM事件流。
事件处理程序
响应某个事件的函数就叫做事件处理程序(或事件侦听器)。
DOM0级事件处理程序
var btn = document.getElementById("myBtn");
btn.onclick = function(){
alert("Clicked");
};
btn.onclick = null; //删除事件处理程序
DOM2级事件处理程序
“DOM2级事件”定义了两个方法,用于处理指定和删除事件处理程序的操作:addEventListener()和removeEventListener()。所有DOM节点中都包含这两个方法,并且它们都接受3个参数:要处理的事件名、作为事件处理程序的函数和一个布尔值。最后这个布尔值参数如果是true,表示在捕获阶段调用事件处理程序;如果是false,表示在冒泡阶段调用事件处理程序。
要在按钮上为click事件添加事件处理程序:
var btn = document.getElementById("myBtn");
btn.addEventListener("click", function() {
alert(this.id);
}, false);
该事件会在冒泡阶段被触发(因为最后一个参数是false)。使用DOM2级方法添加事件处理程序的主要好处是可以添加多个事件处理程序:
var btn = document.getElementById("myBtn");
btn.addEventListener("click", function() {
alert(this.id);
}, false);
btn.addEventListener("click", function() {
alert("Hello world!");
}, false);
通过addEventListener()添加的事件处理程序只能使用removeEventListener()来移除;移除时传入的参数与添加处理程序时使用的参数相同。这也意味着通过addEventListener()添加的匿名函数将无法移除:
var btn = document.getElementById("myBtn");
btn.addEventListener("click", function() {
alert(this.id);
}, false);
//这里省略了其他代码
btn.removeEventListener("click", function() { //没有用!
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); //有效!
大多数情况下,都是将事件处理程序添加到事件流的冒泡阶段,这样可以最大限度地兼容各种浏览器。最好只在需要在事件到达目标之前捕获它的时候将事件处理程序添加到捕获阶段。如果不是特别需要,我们不建议在事件捕获阶段注册事件处理程序。
IE9FirefoxSafariChrome Opera支持DOM2级事件处理程序。
IE事件处理程序
IE实现了与DOM中类似的两个方法:attachEvent()和detachEvent()。这两个方法接受相同的两个参数:事件处理程序名称和事件处理程序函数。由于IE8及更早版本只支持事件冒泡,所以通过attachEvent()添加的事件处理程序都会被添加到冒泡阶段。
var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function() {
alert("Clicked");
});
在IE中使用attachEvent()与使用DOM0级方法的主要区别在于事件处理程序的作用域。在使用DOM0级方法的情况下,事件处理程序会在其所属元素的作用域内运行;在使用attachEvent()方法的情况下,事件处理程序会在全局作用域中运行,因此this等于window:
var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function() {
alert(this === window); //true
});
与addEventListener()类似,attachEvent()方法也可以用来为一个元素添加多个事件处理程序:
var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function() {
alert("Clicked");
});
btn.attachEvent("onclick", function() {
alert("Hello world!");
});
不过,与DOM方法不同的是,这些事件处理程序不是以添加它们的顺序执行,而以相反的顺序被触发(IE8下)。单击这个例子中的按钮,首先看到的是“Hello world!”,然后才是“Clicked”。
使用attachEvent()添加的事件可以通过detachEvent()来移除,条件是必须提供相同的参数,与DOM方法一样,这也意味着添加的匿名函数将不能移除:
var btn = document.getElementById("myBtn");
var handler = function() {
alert("Clicked");
};
btn.attachEvent("onclick", handler);
//这里省略了其他代码
btn.detachEvent("onclick", handler);
支持IE事件处理程序的浏览器有IE和Opera。