js事件捕获冒泡

238 阅读4分钟

首先介绍js绑定事件的几种方式

1.

ele.onxxx = function (event) {}
<div onclick = "console.log('a')"></div>
兼容性很好, 但是一个元素只能绑定一个处理程序
基本等同于写在HTML行间上(在div里面写和在script 里写效果是一样的,注意写在行间里不用写函数,直接写执行语句),因此 on 的绑定方式也俗称句柄的绑定方式。

2.

obj.addEventListener(type, fn, false);

obj.addEventListener(‘事件类型’,处理函数,false)
IE9以下不兼容,可以为一个事件绑定多个处理程序
一个对象的一个事件绑定同一个函数绑定多次,不可以执行多次(地址相同)

<div style="width:100px;height:100px;background-color:red;"></div>
<script>   
     var div = document.getElementsByTagName('div')[0];    
        div.addEventListener('click', function () 
                    {  console.log('a');},false);
</script>

3.

obj.attachEvent(‘on’ + type, fn);
IE独有,一个事件同样可以绑定多个处理程序
div.attachEvent('on' + 事件类型,处理函数);
一个对象的一个事件绑定同一个函数绑定多次,可以执行多次(地址相同)

冒泡和捕获

事件处理模型——事件冒泡、捕获(一个对象的一个事件类型上面绑定的一个处理函数只能绑定一个事件类型,就是可以绑定绑定多个函数,但绑定一个函数时只能绑定一个事件类型)

事件冒泡:结构上(非视觉上)嵌套关系的元素,会存在事件冒泡的功能,即同一事件,自子元素冒泡向父元素。(自底向上)注意:一定是程序结构上的嵌套关系,而非视觉显示上的,冒泡为自子元素向父元素(所以下面的例子为当点击黄色方块时,先显示box,之后依次为content,wrapper

<!DOCTYPE html>
<html lang="en">
<head>   
    <meta charset="UTF-8">    
    title>Document</title>    
    <style type="text/css">        
        .wrapper{            
             width: 300px;            
             height: 300px;            
             background-color: red;        
                }        
        .content{            
             width: 200px;            
             height:200px;            
             background-color:green;        
                }        
        .box{            
            width: 100px;            
            height:100px;            
            background-color:orange;        
            }    
    </style>
</head>
<body> 
    <div class="wrapper">     
        <div class="content">         
        <div class="box"></div>     
        </div> </div>
    <script>    
        var wrapper = document.getElementsByClassName('wrapper')[0];    
        var content = document.getElementsByClassName('content')[0];    
        var box = document.getElementsByClassName('box')[0];    
        wrapper.addEventListener('click', function () {        
                                            console.log('wrapper')    
                                           }, false);        
        content.addEventListener('click', function () {        
                                            console.log('content')    
                                           }, false);    
        box.addEventListener('click', function () {        
                                            console.log('box')    
                                           }, false);
    </script>
</body>
</html>


事件捕获:把false变成true就变成捕获了IE8没有捕获事件

结构上(非视觉上)嵌套关系的元素,会存在事件捕获的功能,即同一事件,自父元素捕获至子元素(事件源元素)。(自底向上)
(如下面当点击黄色方框时,依次显示wrapper,content,box,其中wrapper 和content叫做捕获事件并且执行,而box只能叫做事件执行,因为点击的就是box黄色区域,只是进行常规执行)
<!DOCTYPE html>
<html lang="en">
<head>   
    <meta charset="UTF-8">    
    title>Document</title>    
    <style type="text/css">        
        .wrapper{            
             width: 300px;            
             height: 300px;            
             background-color: red;        
                }        
        .content{            
             width: 200px;            
             height:200px;            
             background-color:green;        
                }        
        .box{            
            width: 100px;            
            height:100px;            
            background-color:orange;        
            }    
    </style>
</head>
<body> 
    <div class="wrapper">     
        <div class="content">         
        <div class="box"></div>     
        </div> </div>
    <script>    
        var wrapper = document.getElementsByClassName('wrapper')[0];    
        var content = document.getElementsByClassName('content')[0];    
        var box = document.getElementsByClassName('box')[0];    
        wrapper.addEventListener('click', function () {        
                                            console.log('wrapper')    
                                           }, true);        
        content.addEventListener('click', function () {        
                                            console.log('content')    
                                           }, true);    
        box.addEventListener('click', function () {        
                                            console.log('box')    
                                           }, true);
    </script>
</body>
</html>


捕获和冒泡同时进行

触发顺序,先捕获,后冒泡(一个对象的一个事件类型绑定了两个处理函数,一个事件冒泡,一个事件捕获)

第一次实验(捕获放前,冒泡放后)

 var wrapper = document.getElementsByClassName('wrapper')[0];    
 var content = document.getElementsByClassName('content')[0];    
 var box = document.getElementsByClassName('box')[0];    
 wrapper.addEventListener('click', function () {        
    console.log('wrapper')    }, true);        
 content.addEventListener('click', function () {       
    console.log('content')    }, true);    
 box.addEventListener('click', function () {        
    console.log('box')    }, true);      
 wrapper.addEventListener('click', function () {        
    console.log('wrapperBubble')    }, false);        
 content.addEventListener('click', function () {        
    console.log('contentBubble')    }, false);    
 box.addEventListener('click', function () {        
    console.log('boxBubble')    }, false);


第二次实验(冒泡放前,捕获放后)

var wrapper = document.getElementsByClassName('wrapper')[0];    
var content = document.getElementsByClassName('content')[0];    
var box = document.getElementsByClassName('box')[0];    
wrapper.addEventListener('click', function () {        
    console.log('wrapperBubble')    }, false);        
content.addEventListener('click', function () {        
    console.log('contentBubble')    }, false);    
box.addEventListener('click', function () {        
    console.log('boxBubble')    }, false);    
wrapper.addEventListener('click', function () {        
    console.log('wrapper')    }, true);        
content.addEventListener('click', function () {        
    console.log('content')    }, true);    
box.addEventListener('click', function () {        
    console.log('box')    }, true);


正常顺序是先捕获后冒泡,但为什么两次结果不一样呢,因为两次实验同样点击了黄色区域,首先先捕获wrapper,之后捕获content,之后因为两次实验都是点击的黄色区域,所以黄色区域是事件,而事件的执行顺序是谁先绑定先执行谁,所以第二次先执行的boxBubble,后执行的box,第一次先执行的box,后执行的boxBubble,之后两次实验一样,content冒泡,wrapper冒泡;