您的位置:

JS阻止事件冒泡

在前端开发中,我们通常要处理很多与鼠标、键盘等用户交互相关的事件。但是,有时候这些事件会冒泡到它们的父元素或者祖先元素中,从而影响到页面的其他部分。幸运的是,我们可以通过JS阻止事件冒泡来避免这种情况发生。本文将会从多个方面详细介绍JS阻止事件冒泡的方法和应用场景。

一、JS阻止事件冒泡的方法

在介绍具体的JS阻止事件冒泡方法之前,我们先来了解一下事件冒泡的概念。当鼠标在某个元素上触发一个事件时,这个事件会向该元素的父级元素冒泡,直到冒泡到document对象为止。下面是JS阻止事件冒泡的几种常见方法:

1. stopPropagation()

使用stopPropagation()方法可以阻止事件冒泡。这个方法是事件对象的一个方法,用来停止事件传播,防止触发父级元素的同名事件。具体的调用方式如下:

  
    document.querySelector('#child').addEventListener('click', function(event) {
      event.stopPropagation();
      console.log('child clicked');
    });
  

上面的代码中,当鼠标在id为child的元素上点击时,click事件不会向其父元素冒泡,因为我们使用了stopPropagation()方法阻止了事件的传播。因此,当我们在child元素上点击时,控制台只会输出'child clicked',而不会输出'parent clicked'。

2. stopImmediatePropagation()

有时候一个元素上会同时绑定多个事件处理函数,如果你想阻止所有的事件冒泡并且阻止该元素上的所有其他事件处理函数的执行,可以使用stopImmediatePropagation()方法。它的调用方式和stopPropagation()类似,只不过它可以防止元素上其他的事件处理函数执行。下面是一个使用stopImmediatePropagation()方法的例子:

  
    document.querySelector('#child').addEventListener('click', function(event) {
      event.stopImmediatePropagation();
      console.log('child clicked');
    });

    document.querySelector('#child').addEventListener('click', function(event) {
      console.log('child clicked again');
    });
  

上面的代码中,当我们在id为child的元素上点击时,事件不仅不会向其父元素冒泡,而且不会执行child元素上其他的事件处理函数。当我们点击元素时,在控制台中只会输出'child clicked',不会输出'child clicked again'。

3. addEventListener(options)

在addEventListener的第二个参数中,你可以传递一个options对象来指定事件处理函数的行为。其中的passive属性可以设置为true来防止事件传播。这个方法是比较新的方法,在较老的浏览器中可能不支持。下面是一个使用addEventListener()的例子:

  
    document.querySelector('#child').addEventListener('click', function(event) {      
      console.log('child clicked');
    }, { passive: true });
  

需要注意的是,在某些高频事件(例如touchmove等)中使用passive可以提高性能。

二、JS阻止冒泡和默认事件

在前端开发中,有时候我们需要同时阻止事件冒泡和默认事件的执行。默认事件是指浏览器对某些事件的默认行为的处理方式,例如当我们在一个链接上点击时,浏览器默认会打开链接地址。下面是一种同时阻止事件冒泡和默认事件的方法:

  
    document.querySelector('#child').addEventListener('click', function(event) {
      event.preventDefault();
      event.stopPropagation();
      console.log('child clicked');
    });
  

在这个例子中,我们使用event.preventDefault()来阻止默认事件,使用event.stopPropagation()来阻止事件冒泡。这样就可以在不影响元素的默认行为的情况下阻止事件冒泡了。

三、JS阻止冒泡和捕获

在事件传播过程中,从最外层的元素往目标元素方向传播的过程称为事件捕获,而从目标元素往最外层元素方向传播的过程称为事件冒泡。默认情况下,addEventListener()方法被调用时,第三个参数useCapture默认为false,即默认使用事件冒泡。我们可以把该参数设置为true来使用事件捕获。下面是使用事件捕获和阻止事件冒泡的例子:

  
    document.querySelector('html').addEventListener("click", function(event) {
      console.log("html clicked");
    }, true);

    document.querySelector('body').addEventListener("click", function(event) {
      event.stopPropagation();
      console.log("body clicked");
    }, true);

    document.querySelector('#child').addEventListener("click", function(event) {
      console.log("child clicked");
    }, true);
  

在这个例子中,我们可以看到当鼠标点击child元素时,事件会从最外层的html元素被捕获,向下传递到了body元素,接着到了child元素,而且click事件也不会继续往上传到body和html元素。这是因为我们在body元素上调用了event.stopPropagation()方法。而当我们在body或者html上点击时,它们的点击事件不会冒泡给child元素。

四、JS阻止事件冒泡的两种方法

除了上面提到的stopPropagation()和stopImmediatePropagation()之外,还有两种阻止事件冒泡的方法:

1. return false

在事件处理函数中使用return false可以阻止事件冒泡。例如:

  
    document.querySelector('#child').addEventListener('click', function(event) {
      console.log('child clicked');
      return false;
    });
  

在这个例子中,当我们在child元素上点击时,事件不会冒泡给parent元素了,因为我们在事件处理函数中返回了false。需要注意的是,return false不仅会阻止事件冒泡,还会阻止默认事件的执行。

2. onclick

可以在HTML中使用onclick属性来指定元素被点击时的处理函数,并且使用return false来阻止事件冒泡和默认事件。例如:

  
    <div id="child" onclick="console.log('child clicked'); return false;">child</div>
  

在这个例子中,当我们在child元素上点击时,事件不会向其父元素冒泡,而且也不会执行浏览器默认的行为。

五、原生JS阻止事件冒泡的方法

在原生的JS中,我们也可以使用return false或者event.stopPropagation()来阻止事件冒泡。例如:

  
    document.getElementById('child').onclick = function(event) {
      console.log('child clicked');
      return false;
    };
  

需要注意的是,当我们使用原生的JS时,请勿在事件处理函数中使用return false和调用event.preventDefault(),因为这会导致一些错误,例如IE浏览器中会出现无法禁用链接的情况。

六、JS阻止事件冒泡不起作用

有时候,阻止事件冒泡的方法并不起作用,这可能是由于事件处理函数的执行时间较长,导致无法成功阻止事件冒泡。这时候我们可以使用setTimeout()函数来解决这个问题。例如:

  
    document.querySelector('#child').addEventListener('click', function(event) {      
      setTimeout(function() {
        event.stopPropagation();
        console.log('child clicked');
      }, 100);
    });
  

在这个例子中,我们使用了setTimeout()函数来延迟事件处理函数的执行时间,使事件能够成功地被阻止冒泡。

七、Vue阻止事件冒泡

在Vue中,可以使用.stop修饰符来阻止事件冒泡。例如:

  
    <div id="child" @click.stop="handler">child</div>
  

在这个例子中,我们使用@click事件监听给child元素绑定了一个事件处理函数handler,并使用.stop修饰符阻止了事件冒泡。也可以使用@mousedown.stop等事件在Vue中阻止事件冒泡。

八、CSS阻止事件冒泡

在CSS中,可以使用pointer-events属性阻止事件往下传递。例如:

  
    #child {
      pointer-events: none;
    }
  

在这个例子中,我们使用pointer-events: none来阻止了child元素上的所有事件(包括鼠标和键盘事件)。