JavaScript和HTML之间的交互是通过事件来完成的。事件最早在IE3和Netscape3中出现。从DOM2级规范开始尝试以一种符合逻辑的方式来标准DOM事件。Firefox、Chrome、Safari和Opera浏览器都实现了“DOM级事件”。IE浏览器是唯一一个使用专用事件系统的浏览器。
JavaScript事件是一种异步事件,也就是说,这些事件随时都有可能发生。引发事件发生的动作称之为触发事件,例如鼠标滑过一个按钮,用户点击了某个超链接等,都会触发相应的事件。
事件流
随着浏览器的发展,对事件的处理遇到了一个有趣的问题:一个事件属于页面的哪个特定部分?换句话来说,如果页面中有一个按钮,那么点击这个按钮的时候事件仅仅发生在按钮上面吗?微软和网景两家公司都认为,如果你单击了一个按钮,那么事件不仅仅发生在按钮上,在你单击了按钮的同时,你也单击了按钮的父容器元素,甚至是单击了这个页面。
事件流描述的是从页面中接收事件的顺序。微软和网景两家公司提出的事件流的概念是完全相反的。IE的事件流是事件冒泡,网景的事件流是事件捕获。
事件冒泡
IE的事件流叫做事件冒泡(event bubbling),它是指事件最初由最具体的元素接收,然后逐级向上传播到较为不具体的节点。例如有下面的HTML代码:
<html lang="zh"> <head> <meta charset="UTF-8"> <title>JavaScript事件</title> </head> <body> <button id="btn">点击一下</button> </body> </html>
如果你点击了页面中的按钮,那么事件将按照如下的顺序进行传播:
<button>
→<body>
→<html>
→<document>
也就是说,点击事件实际发生在<button>
元素上,然后事件会沿着DOM树向上传播,在每一个DOM节点上都会发生,一直传播到document对象。
所有的现代浏览器都支持事件冒泡,但是在具体实现上略有差别。
事件捕获
网景公司提出的事件流是事件捕获(event capturing)。事件捕获的思想是不具体的节点应该更早的接收到事件,最具体的节点最后才接收到事件。事件捕获的用意在于在事件到达预定的目标之前捕获它。还是以上面的HTML页面的代码为例子,在点击了按钮之后,事件的传播方式为:
<document>
→<html>
→<body>
→<button>
在事件捕获的过程中,document对象首先接收到点击事件,然后事件会沿着DOM树依次向下,一直传播到事件的目标元素。
Firefox、Chrome、Safari和Opera浏览器都支持事件捕获。“DOM2级事件”要求事件应该从document对象开始传播,但是上面的4种浏览器都从window对象开始捕获事件。
DOM事件流
“DOM2级事件”规定的事件流包括3个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段。首先发生的是事件捕获,这为截获事件提供了机会。接着是实际触发事件的目标。最后是事件冒泡,可以在这个阶段对事件作出响应。还是以前面的HTML代码为例,单击按钮元素后会按照下图所示的顺序触发事件。
在DOM事件流中实际的目标元素(按钮)在事件捕获阶段不会接受到事件。这意味着在事件捕获阶段,事件从document到<html>
再到<body>
就停止了。然后接着是“处于目标”阶段,这时事件在按钮上发生,这个阶段被看成是事件冒泡的一部分。最后是事件冒泡阶段,事件又传播回文档中。
虽然“DOM2级事件”规范明确规定捕获阶段不会涉及事件目标,但是Firefox、Chrome、Safari和Opera浏览器都会在捕获阶段触发事件对象上的事件。这将给我们两个机会在目标元素上操作事件。
另外,Firefox、Chrome、Safari和Opera浏览器都支持DOM事件流,但是IE不支持DOM事件流。