冒泡与捕获

先上代码

    <div id="a">
        a
        <div id="b">
            b
            <div id="c">
                c
            </div>
        </div>
    </div>
   document.getElementById('a').addEventListener('click', function(){
       console.log('a')
   })
   document.getElementById('b').addEventListener('click', function(){
       console.log('b')
   })
   document.getElementById('c').addEventListener('click', function(){
       console.log('c')
   })  

点击c区域,输出的顺序是 c b a

js事件的运行有2个阶段,一个是捕获阶段,一个是冒泡阶段,捕获阶段执行顺序是a-b-c,而冒泡阶段则相反,是c-b-a,事件是默认绑定在冒泡阶段的

上面的解释可以清楚为什么输出的顺序是c-b-a

如果想要点击c 时输出a-b-c要怎么做呢?可以使用addEventListener方法的useCapture参数,它默认是false,即绑定事件默认在冒泡阶段,如果设置为true,则父元素绑定的事件先执行

   document.getElementById('a').addEventListener('click', function(){
       console.log('a')
   },true)
   document.getElementById('b').addEventListener('click', function(){
       console.log('b')
   },true)
   document.getElementById('c').addEventListener('click', function(){
       console.log('c')
   },true)  

阻止冒泡和捕获
stopPropagation

这个方法可以阻止冒泡,也可以阻止捕获,即只执行当前点击元素的事件

   document.getElementById('a').addEventListener('click', function(e){
       console.log('a')
       e.stopPropagation()
   },true)
   document.getElementById('b').addEventListener('click', function(){
       console.log('b')
   },true)
   document.getElementById('c').addEventListener('click', function(){
       console.log('c')
   },true) 

stopImmediatePropagation

这个方法可以阻止冒泡和捕获,同时可以阻止该元素上同类事件被触发

   document.getElementById('a').addEventListener('click', function(e){
       console.log('a1')
       e.stopImmediatePropagation()
   },true)
   document.getElementById('a').addEventListener('click', function(e){
       console.log('a2')
   },true)

如上代码,只会输出a1,不会输出a2