如何停止将事件从 parent div 传播到 child div

How to stop propagating event from parent div to child div

我想停止在我的 html 中将事件从 parent div 传播到 child div。这是我正在尝试做的简单代码:

<div>
  <div id='categoryList'>
    <div class='listed-category'>
      <span>some content</span>
      <a id='close'>x</a> //"a" is used to remove the div
    </div>
  </div>
</div>
<div id='dropdown'>
</div>

在上面的代码中,如果我点击 <div id='categoryList'><div id='dropdown'> 将 slide-up 并通过下面的代码向下。

$(document).ready(function () {

    $('#categoryList').click(function (event) {
        event.preventDefault();
        event.stopPropagation();
        if ($('#dropdown').is(":visible")) {
            $('#dropdown').slideUp(400);
        }
        else {
            $('#dropdown').slideDown(400);
        }
    });
})

但是当我点击 child <div class='listed-category'> 上面的 JavaScript 执行并且 <div id='dropdown'> 上下滑动。如何阻止这个?但是我希望能够单击 <a id='close'> 以删除 child div

检查匹配点击对象的目标。在单击事件处理程序的开头尝试此代码。

if( event.target !== this ) {
       return;
}
//...do stuff.. 

你需要停止在 child 中传播,而不是 parent 所以你应该这样写:

 $('.listed-category').click(function(event){
    event.stopPropagation();
});

如果你想点击a标签并停止传播,你还需要这样写:

 $('a#close').click(function(event){
    event.stopPropagation();
});

无论如何我都会推荐 Yuriy 的答案。我只是想让你知道你应该把 event.stopPropagation() 放在 childrens 中(如果你不希望 parent 的事件是 运行),而不是 parent.

http://codepen.io/rakeshcode/pen/KrZdNo

$(document).ready(function(){
  $(".arrow").click(function(){
  $(".row").slideToggle();
  
  });

$(".btn").click(function(event){
   event.stopPropagation();
  //$(".btn").attr("href","www.yahoo.com")
});
})
.btn {
  display: block;
  padding:15px;
  background-color:green;
  width:100px;
  margin-top:15px;
  text-decoration:none;
  margin-left:auto;
  margin-right:auto;
  
  
  
}
.arrow {
  cursor:pointer;
  text-align: center;
  padding:10px 0;
  font-size:15px;
  font-weight:bold;
  background-color:grey;
  margin-top:15px;
}
.container {
  max-width:600px;
  margin-left:auto;
  margin-right:auto; 
}
.close {
  height:75px;
  overflow:hidden;
  transition-duration: 0.3s;  
  transition-timing-function: cubic-bezier(0, 1, 0.5, 1);
}
.open {
  height:215px;
  overflow: hidden;
  transition-property:height;
  -moz-transition-duration: 0.3s;
    -webkit-transition-duration: 0.3s;
    -o-transition-duration: 0.3s;
    transition-duration: 0.3s;  
  transition-timing-function: ease-in;
}
.up {
  background-color:red; 
}
.down {
  background-color:green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <div class="arrow"> Click here Click here<a class="btn" href="www.google.com" target="_blank">click here</a></div>
  <div class="wrap">
  <div class="row">The most effective plac elearning,’ they most likely don’t know this themselves.Well, the most effective place to start is to dig into what the person asking for this training, ACTUALLY needs. Because if they’re dumping a huge stack of content on your desk and giving you vague instructions to ‘turn it into elearning,’ they most likely don’t know this themselves.Well, the most effective place to start is to dig into what the person asking for this training.ACTUALLY needs. Because if they’re dumping a huge stack of content on your desk and giving you vague instructions to ‘turn it into elearning,’ they most likely don’t know this themselves.Well, the most effective place to start is to dig into what the person asking for this trainingACTUALLY needs. Because if they’re dumping a huge stack of content on your desk and giving you vague instructions to ‘turn it into elearning,’ they most likely don’t know this themselves.Well, the most effective place to start is to dig into what the person asking for this training</div>
  </div>
  </div>

我建议您在 div <div class='listed-category'> 中使用 unbind() 方法而不是使用 e.stopPropagation 方法...

$('.listed-category').unbind('click');

这将允许停止 .listed-category div 的传播效果。 e.stopPropagation() 方法不起作用,因为它只适用于父元素而不适用于子元素。

您可以随时创建一个新函数并在之后分配给 .listed-category div。您也可以在 link 查看 unbind() 方法的文档: http://api.jquery.com/unbind/

希望对您有所帮助!

接受的答案是正确的,但在您有多个嵌套元素的最佳情况下,您不希望取消事件,而是获取实际单击的父容器并使用它。

$('.clicked-container').click((e) => {
    let t = e.target;
    while (!$(t).hasClass( "clicked-container" )) { t = t.parentNode; }
     
    ...
    $(t).toggleClass('active-or-whatever-you-want');
});

此外,当您在 ES6 中使用 Arrows => 时,已接受答案中的“this”不再指代同一事物。您必须明确绑定它。

在 React 上使用 ref 防止事件冒泡的示例:

import React, { useRef } from "react";

const Modal = ({
  onClick,
}) => {
  const modalRef = useRef();

  return (
    <div
      ref={modalRef}
      onClick={(e) => {
        if (e.target !== modalRef.current) {
          return;
        }
        onClick();
      }}
    >
    </div>
  );
};

export default Modal;

参考

一个更优雅的解决方案是使用 CSS 并禁用子项上的指针事件。

#categoryList * {
    pointer-events: none;
}

或者在您的特定情况下 listed-category 元素上没有事件:

#listed-category {
    pointer-events: none;
}