用户在点击网页上某一按钮时,浏览器会想办法接收这一操做,如何接收呢? 浏览器会为点击操做划定若干个范围,从小到大依次是按钮自己,包含这个按钮的元素, 最后就是整个页面。这一操做称为事件,而接收事件的次序称为事件流。 事件流总共有两种形式:事件冒泡,事件捕获。javascript
事件冒泡就是从小到大,从具体对象到不具体对象,像泡泡同样逐级向上html
<html></html> <body> <div id="div1"> <div id="div2"> <button>click me!</button> </div> </div> </body>
当用户打开上述代码编写的页面,点击按钮时,若是浏览器采起的是事件冒泡的事件接收机制, 那么浏览器就先从button元素开始接收,而后是而后是div2,而后是div1,最终到document对象(规范是到document为止, 可是大多数浏览器都会一直冒泡到window对象),如图所示。java
事件捕获就是事件冒泡的反序。从大到小,从不具体对象到具体对象,逐级向下。浏览器
若是浏览器采起的是事件捕获的事件接收机制, 浏览器先从document对象(规范定的是document对象,大多数浏览器是从window对象处开始接收)开始接收, 而后是<html>元素,而后是<body>元素,最后在<button>元素处接收。ui
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <meta http-equiv="contentType" content="text/html" /> <title>Test</title> </head> <body> <div id="div1"> <div id="div2"> <button>click me!</button> </div> </div> <script src="scripts/test.js" type="text/javascript"></script> </body> </html>
var div1 = document.querySelector("#div1"); var div2 = document.querySelector("#div2"); var button = document.querySelector("button"); div1.addEventListener("click",function(event){ console.log("div1"); },false); //传入false,事件冒泡 div2.addEventListener("click",function(event){ console.log("div2"); },false); button.addEventListener("click",function(event){ console.log("button"); },false);
上述代码使用addEventListener()方法,分别为div1,div2,button元素添加了事件处理程序, 并显示的指定事件流为事件冒泡机制,浏览器按具体对象到不具体对象的顺序接收事件。因此控制台输出spa
同一段代码,但显示的指定事件流为事件捕获机制,浏览器按不具体对象到具体对象的顺序接收事件, 控制台输出。设计
理解事件流的这两种机制有什么用?其实这对理解某些DOM事件是颇有好处的,好比mouseover、mouseout、mouseleave、mouseenter。 其中,mouseover和mouseout是一对儿,鼠标进入目标元素时接收mouseover,离开目标元素时接收mouseout事件。 mouseenter和mouseleave是一对儿,鼠标进入目标元素时接收mouseenter,离开目标元素时接收mouseleave事件, 可是他俩不冒泡!因此鼠标进入、离开其后代元素时,其父元素没法接受到mouseenter和mouseleave事件。code
<div id="target"> <p> Lorem Ipsum is simply dummy text of the printing and typesetting industry.<br/> Lorem Ipsum has been the industry's standard dummy text ever since the 1500. </p> <p> Lorem Ipsum is simply dummy text of the printing and typesetting industry.<br/> Lorem Ipsum has been the industry's standard dummy text ever since the 1500. </p> <p> Lorem Ipsum is simply dummy text of the printing and typesetting industry.<br/> Lorem Ipsum has been the industry's standard dummy text ever since the 1500. </p> <p> Lorem Ipsum is simply dummy text of the printing and typesetting industry.<br/> Lorem Ipsum has been the industry's standard dummy text ever since the 1500. </p> </div>
var target = document.querySelector("#target"); /** * 使用mouseenter和mouseleave事件,进入target时浏览器接受mouseenter事件, * 离开target时浏览器接受mouseleave事件。 * 在target中移动鼠标(在各个<p>元素之间切换),由于不冒泡,因此target不会继续接收到mouseenter和mouseleave, * 也就不会调用相应的事件处理程序 */ target.addEventListener("mouseenter",function(event) { console.log("parent mouseenter"); },false); target.addEventListener("mouseleave",function(event) { console.log("parent mouseleave"); },false);
/** * 使用mouseout和mouseover事件, 在target中移动鼠标(在各个<p>元素之间切换),因为事件流是事件冒泡机制, * 因此target就会接收到其子元素冒泡而来的mouseenter和mouseleave,从而调用相应的事件处理机制 */ target.addEventListener("mouseout",function(event) { console.log("parent mouseout"); },false); target.addEventListener("mouseover",function(event) { console.log("parent mouseover"); },false);
如控制带输出所示,鼠标横穿target,mouseenter仅触发了一次,mouseleave也仅触发了一次。而mouseout、mouseover触发了若干次。htm
事件:用户的某一操做对象
事件流:浏览器接受事件的顺序
事件冒泡:从具体对象到不具体对象,逐级向上接收
事件捕获:从不具体对象到具体对象,逐级向下接收
1.《javascript高级程序设计》