对于 JS 中的,事件冒泡和事件捕获你了解多少 ?

前言 :


在页面中,JS 和 HTML 之间的各种交互,是通过一系列的事件去实现的。那么我们就必须要去掌握 JS 中的 事件,事件流,事件冒泡,事件捕获,事件委托 等知识。

  • 事件 ?

事件:是文档或浏览器窗口中发生的一些特定的交互问题。

  • 事件流 ?

事件流:描述的是页面中接受事件的顺序,它分为两种,事件冒泡和事件捕获,现在主流为事件冒泡。IE9,chrome,Firefox,Opera,Safari 均实现了 DOM2 级规范中定义的标准 DOM 事件,而 IE8 和 IE8 以下版本仍然保留专有的事件处理方式。

  • 事件冒泡 ?

事件冒泡:即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播。

在一个对象上触发某类事件(比如单击 onclick 事件),如果此对象定义了此事件的处理程序,那么此事件就会调用这个处理程序,如果没有定义此事件处理程序或者事件返回true,那么这个事件会向这个对象的父级对象传播,从里到外,直至它被处理(父级对象所有同类事件都将被激活),或者它到达了对象层次的最顶层,即 document 对象(有些浏览器window)。

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>Event Bubbling Example</title>
    </head>
    <style type="text/css">
        #myDiv{
            width:100px;
            height:100px;
            background-color:#FF0000;
        }
    </style>
    <body>
        <div id="myDiv"></div>
    </body>  
    <script type="text/javascript">
        var div=document.getElementById("myDiv");
        div.onclick=function(event){
            alert("div");
        };
        document.body.onclick=function(event){
            alert("body");
        };    
    </script>  
</html>

实例解析:当用户点击了 <div> 元素,click 事件将按照 <div>—><body>—><html>—>document 的顺序进行传播。若在<div> 和 <body> 上都定义了click事件,点击<div>,将先输出 “div”,再输出 “body”。IE9,chrome,Firefox,Opera,Safari 都支持事件冒泡,并将事件冒泡到 window 对象。

  • 事件捕获 ?

事件捕获:是先由最上一级的节点先接收事件,然后向下传播到具体的节点。

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>Event Bubbling Example</title>
    </head>
    <style type="text/css">
        #myDiv{
            width:100px;
            height:100px;
            background-color:#FF0000;
        }
    </style>
    <body>
        <div id="myDiv"></div>
    </body>
    <script type="text/javascript">
        var div=document.getElementById("myDiv");    
        div.addEventListener("click",function(event){
            alert("div");
        },true);
        document.body.addEventListener("click",function(event){
            alert("body");
        },true);
        
    </script>    
</html>

实例解析:采用事件捕获,则 click 事件将按照 document—><html>—><body>—><div> 的顺序进行传播。若在 <div>和<body> 上都定义了 click 事件,点击 <div>,将先输出“body”,再输出 “div”。IE9,chrome,Firefox,Opera,Safari 都支持事件捕获,但是 IE8 和 IE8 以下的版本只支持事件冒泡。尽管 DOM2 规范要求事件应该从 document 对象开始传播,但是现在的浏览器实现都是从 window 对象开始捕获事件。

  • DOM 事件流 ?

"DOM2级事件”:规定的事件流包含三个阶段:事件捕获阶段,处于目标阶段和事件冒泡阶段。首先发生的是事件捕获,然后是实际的目标接收到事件,最后阶段是冒泡阶段。

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>Event Bubbling Example</title>
    </head>
    <style type="text/css">
        #myDiv{
            width:100px;
            height:100px;
            background-color:#FF0000;
        }
    </style>
    <body>
        <div id="myDiv"></div>
    </body>
    <script type="text/javascript">
        var div=document.getElementById("myDiv");    
        div.onclick=function(event){
            alert("div");
        };
        document.body.addEventListener("click",function(event){
            alert("event bubble");
        },false);
        document.body.addEventListener("click",function(event){
            alert("event catch");
        },true);
        
    </script>
</html>

实例解析若在 <div> 和 <body> 上都定义了 click 事件,点击 <div>,将先输出 “event catch”,再输出 “div”,最后输出 “event bubble”。

  • 事件委托机制 ?

事件委托机制:由冒泡事件衍生出的事件委托机制,既然事件是冒泡传递的,那可以让某个父节点统一处理事件,通过判断事件的发生地(即事件产生的节点),然后做出相应的处理。就是将子元素的事件处理程序绑定到父类上,例如常见的ul>li> a 列表标签的写法应用。

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>Event Bubbling Example</title>
    </head>
    <body>
    <ul>
       <li id="ll">选项一</li>
       <li>选项二</li>
       <li>选项三</li>
       <li>选项四</li>
    </ul>
    </body>
    <script type="text/javascript">
       $("ul").on("mouseover", function () {
        console.log(event.target);
        var lis = document.getElementsByTagName("li");
        for (var i = 0; i < lis.length; i++) {
            if (event.target && event.target == lis[i]) {
                $(event.target).css("background-color", "#ffff00").siblings().css("background-color", "#1d7b15");
        }
    }
});
    </script>
</html>
  • 阻止冒泡 ?
function stopBubble(e) { 
//如果提供了事件对象,则这是一个非IE浏览器 
    if ( e && e.stopPropagation ) {
        //因此它支持W3C的stopPropagation()方法 
        e.stopPropagation(); 
    }else{ 
        //否则,我们需要使用IE的方式来取消事件冒泡 
        window.event.cancelBubble = true; 
    }
}
  • 阻止事件默认行为 ?
//阻止浏览器的默认行为 
function stopDefault( e ) { 
    //阻止默认浏览器动作(W3C) 
    if ( e && e.preventDefault ){ 
        e.preventDefault(); 
    //IE中阻止函数器默认动作的方式 
    }else{ 
        window.event.returnValue = false; 
    }
    return false; 
}
  • jQuery 阻止事件冒泡 ?
// 方法1
$("#div1").mousedown(function(event){
    event.stopPropagation();
});

// 方法2
$("#div1").mousedown(function(event){
    return false;
});

【注意】:这两种方式是有区别的。return false 不仅阻止了事件往上冒泡,而且阻止了事件本身。event.stopPropagation() 则只阻止事件往上冒泡,不阻止事件本身。在 jq 下,即阻止默认行为又停止冒泡。js 原生下,阻止默认行为,不会停止冒泡。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值