~ 事件流

浏览器发展到第四代时(IE4及Netscape4),浏览器开发团队遇到了一个很有意思的问题:页面的哪一部分会拥有某个特定的事件?想象一张纸上的一组同心圆:把手指放在圆心上,那么手指指向的不是一个圆,而是纸上的所有圆。

两家公司的浏览器开发团队在看待浏览器事件方面还是一致的。如果单击了某个按钮,他们都认为单击事件不仅仅发生在按钮上,甚至也单击了整个页面。但有意思的是,IE和Netscape开发团队居然提出了差不多是完全相反的事件流的概念。IE的事件流是事件冒泡流,而Netscape的事件流是事件捕获流。


事件的三个阶段

所谓事件流,就是说页面中接收事件的顺序,主要分为 3 个阶段:

  • 事件捕获阶段(capture phase),为截获事件提供了机会;
  • 处于目标阶段(target phase),即,实际的目标接收到事件;
  • 事件冒泡阶段(bubbling phase),可以在这个阶段对事件作出响应。

[1] 事件捕获阶段                    // 老版本浏览器不支持,建议使用事件冒泡,特殊需要再使用事件捕获。

事件捕获的思想是不太具体的节点应该更早接收到事件,而最具体的节点应该最后接收到事件,用意在于在事件到达预定目标前捕获它。E9、Firefox、Chrome、Safari等现代浏览器都支持事件捕获,但是从window对象开始捕获。

addEventListener()方法中的第三个参数设置为true时,即为事件捕获阶段。

<!DOCTYPE HTML>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <title>Document</title>
<body>
   <div id="box" style="height:100px;width:300px;background-color:pink;"></div>
   <button id="reset">还原</button>
   <script>
      // IE8-浏览器不支持
      // 其他浏览器返回 window document html body div
      reset.onclick = function(){history.go();}
      box.addEventListener('click',function(){box.innerHTML += 'div\n'},true)
      document.body.addEventListener('click',function(){box.innerHTML += 'body\n';},true);
      document.documentElement.addEventListener('click',function(){box.innerHTML += 'html\n';},true);
      document.addEventListener('click',function(){box.innerHTML += 'document\n';},true);
      window.addEventListener('click',function(){box.innerHTML += 'window\n';},true);
   </script>
</body>    
</html>

[2] 处于目标阶段


[3] 事件冒泡阶段

IE的事件流,叫做事件冒泡(event bubbling),即事件开始时由最具体的元素(文档中嵌套层次最深的节点)接收,然后逐级向上传播到较为不具体的节点(文档)。浏览器默认支持事件冒泡,但IE9、Firefox、Chrome、Safari一直冒泡到window对象。

<!DOCTYPE HTML>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <title>Document</title>
<body>
   <div id="box" style="height:100px;width:300px;background-color:pink;"></div>
   <button id="reset">还原</button>
   <script>
   // IE8-浏览器返回div body html document
   // 其他浏览器返回div body html document window
      reset.onclick = function(){history.go();}
      box.onclick = function(){box.innerHTML += 'div\n';}
      document.body.onclick = function(){box.innerHTML += 'body\n';}
      document.documentElement.onclick = function(){box.innerHTML += 'html\n';}
      document.onclick = function(){box.innerHTML += 'document\n';}
      window.onclick = function(){box.innerHTML += 'window\n';}
   </script>
</body>    
</html>