事件及事件流

事件与事件流

用户在点击网页上某一按钮时,浏览器会想办法接收这一操作,如何接收呢? 浏览器会为点击操作划定若干个范围,从小到大依次是按钮本身,包含这个按钮的元素, 最后就是整个页面。这一操作称为事件,而接收事件的次序称为事件流。 事件流总共有两种形式:事件冒泡事件捕获

事件冒泡

事件冒泡就是从小到大,从具体对象到不具体对象,像泡泡一样逐级向上

<html></html>
<body>
    <div id="div1">
        <div id="div2">
            <button>click me!</button>
        </div>
    </div>
</body>

当用户打开上述代码编写的页面,点击按钮时,如果浏览器采取的是事件冒泡的事件接收机制, 那么浏览器就先从button元素开始接收,然后是然后是div2,然后是div1,最终到document对象(规范是到document为止, 但是大多数浏览器都会一直冒泡到window对象),如图所示。

事件捕获

事件捕获就是事件冒泡的反序。从大到小,从不具体对象到具体对象,逐级向下。

如果浏览器采取的是事件捕获的事件接收机制, 浏览器先从document对象(规范定的是document对象,大多数浏览器是从window对象处开始接收)开始接收, 然后是<html>元素,然后是<body>元素,最后在<button>元素处接收。

<!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元素添加了事件处理程序, 并显示的指定事件流为事件冒泡机制,浏览器按具体对象到不具体对象的顺序接收事件。所以控制台输出

 

同一段代码,但显示的指定事件流为事件捕获机制,浏览器按不具体对象到具体对象的顺序接收事件, 控制台输出。

有什么用

理解事件流的这两种机制有什么用?其实这对理解某些DOM事件是很有好处的,比如mouseover、mouseout、mouseleave、mouseenter。 其中,mouseover和mouseout是一对儿,鼠标进入目标元素时接收mouseover,离开目标元素时接收mouseout事件。 mouseenter和mouseleave是一对儿,鼠标进入目标元素时接收mouseenter,离开目标元素时接收mouseleave事件, 但是他俩不冒泡!所以鼠标进入、离开其后代元素时,其父元素无法接受到mouseenter和mouseleave事件。

 

<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触发了若干次。

总结

事件:用户的某一操作

事件流:浏览器接受事件的顺序

事件冒泡:从具体对象到不具体对象,逐级向上接收

事件捕获:从不具体对象到具体对象,逐级向下接收

 参考资料

1.《javascript高级程序设计》

posted @ 2017-01-16 22:44  付大石  阅读(654)  评论(0编辑  收藏  举报