【问题标题】:How to have click event ONLY fire on parent DIV, not children?如何让点击事件只在父 DIV 上触发,而不是在子 DIV 上触发?
【发布时间】:2012-02-07 20:29:50
【问题描述】:

我有一个带有 foobar 分类的 DIV,以及该 DIV 中的一些未分类的 DIV,但我想它们正在继承 foobar 类:

$('.foobar').on('click', function() { /*...do stuff...*/ });

我希望它仅在单击 DIV 中的某个位置而不是其子 DIV 时触发。

【问题讨论】:

    标签: jquery events onclick


    【解决方案1】:

    如果e.targetthis 是相同的元素,则您没有单击后代。

    $('.foobar').on('click', function(e) {
      if (e.target !== this)
        return;
      
      alert( 'clicked the foobar' );
    });
    .foobar {
      padding: 20px; background: yellow;
    }
    span {
      background: blue; color: white; padding: 8px;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <div class='foobar'> .foobar (alert) 
      <span>child (no alert)</span>
    </div>

    【讨论】:

    • 嗨@vicky。仅供参考,JavaScript 有两种不同的值相等比较。 ===!== 使用“严格等式比较算法”,而==!= 使用“抽象等式比较算法”,即是强制类型。一般的智慧是总是使用 strict 比较,除非对强制类型 有特殊需要(因为它的规则有点复杂)。在这种情况下,因为是比较对象,所以实际上并没有什么区别,但是您会发现大多数人仍然会坚持 strict 比较。
    • @vicky:没关系。它仍然是正确的。只是让你 JS 有不同的运算符。 ;-)
    • @GauravAggarwal:首先使用if 语句的目的是使它下面的代码在单击.foobar 元素的子元素时不会运行。如果我们把警报放在最上面,它就会一直运行。因此,基本上,您应该在单击外部黄色区域时看到警报,而不是蓝色孩子。
    • 这是一个很好的答案,因为它也可以与 Vanilla JS addEventListener 一起使用,并且不是 jQuery 特定的。
    • 如何在 vanilla js 上做到这一点?
    【解决方案2】:

    如果您不介意只针对较新的浏览器,还有另一种可行的方法。只需添加 CSS

    pointer-events: none;
    

    到要捕获点击的 div 的任何子级。这是支持表

    http://caniuse.com/#feat=pointer-events

    【讨论】:

    • 知道我应该避免写“谢谢”cmets,但我可以为此亲吻你的脚 :-)
    • @SimonaAdriani 嗯?
    • 谢谢,我也是这样做的,但我很难围绕它编写单元测试用例。如何确保阻止 click 编程点击事件触发器?
    • 这是不正确的。您可能仍希望允许子元素上的事件,而不是父元素。例如,父元素可能有一个 mouseover 事件,您不希望在作为输入的子元素上发生该事件,但显然您想使用该输入。
    • @Cyber​​netic - 在这种情况下,您可以只处理父级上的单击(或焦点)事件,然后使用 input.focus() 聚焦输入,但无论如何,这个问题有多种解决方案,其中无论如何,某人使用的一个将基于他们的用例。
    【解决方案3】:

    我没有得到公认的工作答案,但这似乎可以解决问题,至少在原版 JS 中是这样。

    if(e.target !== e.currentTarget) return;
    

    【讨论】:

    • e.currentTarget 比引用 this 更准确,因为 this 指向的对象可以根据调用它的范围和上下文而改变
    • event.currentTarget 看起来是这里最干净的方法。
    • 请注意,您也可以这样做if (e.target === e.currentTarget) { ...your code } 为什么这样有效:e.target 是触发事件的元素(例如,用户单击) e.currentTarget 是事件侦听器所在的元素附于。因此,当您比较这两者时,附加事件的元素与单击的元素相同。
    • 感谢该解决方案非常适合我的问题。我观察到的是,当您记录“e”并打开记录的对象时,currentTarget 为空,但是当您记录“e.currentTarget”时,它会正确记录元素。我很困惑为什么?
    • 得到我的答案“因为事件对象的 e.currentTarget 属性在传播时发生了变化”。
    【解决方案4】:

    您可以使用冒泡:

    $('.foobar').on('click', function(e) {
        // do your thing.
    }).on('click', 'div', function(e) {
        // clicked on descendant div
        e.stopPropagation();
    });
    

    【讨论】:

    • 对于我的特定场景,这看起来是一个不错的解决方案,因为我只想排除对后代 &lt;a&gt; 元素的点击。只有一个问题:当我中间单击它们时,事件仍然会触发(在 Google Chrome 中测试)。是否有这种变体也可以防止这种情况发生?
    • @cgogolin,看看这个:stackoverflow.com/questions/12197122/…
    【解决方案5】:
    //bind `click` event handler to the `.foobar` element(s) to do work,
    //then find the children of all the `.foobar` element(s)
    //and bind a `click` event handler to them that stops the propagation of the event
    $('.foobar').on('click', function () { ... }).children().on('click', function (event) {
        event.stopPropagation();
        //you can also use `return false;` which is the same as `event.preventDefault()` and `event.stopPropagation()` all in one (in a jQuery event handler)
    });
    

    这将停止click 事件在.foobar 元素的任何子元素上的传播(冒泡),因此该事件不会到达.foobar 元素触发他们的事件处理程序。

    这是一个演示:http://jsfiddle.net/bQQJP/

    【讨论】:

      【解决方案6】:
      $(".advanced ul li").live('click',function(e){
          if(e.target != this) return;
          //code
          // this code will execute only when you click to li and not to a child
      })
      

      【讨论】:

        【解决方案7】:

        我遇到了同样的问题并想出了这个解决方案(基于其他答案)

         $( ".newsletter_background" ).click(function(e) {
            if (e.target == this) {
                $(".newsletter_background").hide();
            } 
        });
        

        基本上它说如果目标是 div 然后运行代码,否则什么都不做(不要隐藏它)

        【讨论】:

        • 这里可以用箭头函数代替(function(e) {})吗?
        【解决方案8】:

        如果您不能使用pointer-events: none; 并且针对现代浏览器,您可以使用composedPath 来检测对象上的直接点击,如下所示:

        element.addEventListener("click", function (ev) {
            if (ev.composedPath()[0] === this) {
                // your code here ...
            }
        })
        

        您可以在此处阅读有关composedPath 的更多信息: https://developer.mozilla.org/en-US/docs/Web/API/Event/composedPath

        【讨论】:

          【解决方案9】:

          我的情况类似,但这是您很少有foobar-s,并且您只想关闭一个 - 每次点击:

          查找父案例

          $(".foobar-close-button-class").on("click", function () {
              $(this).parents('.foobar').fadeOut( 100 );
              // 'this' - means that you finding some parent class from '.foobar-close-button-class'
              // '.parents' -means that you finding parent class with name '.foobar'
          });
          

          查找子案例

          $(".foobar-close-button-class").on("click", function () {
              $(this).child('.foobar-close-button-child-class').fadeOut( 100 );
              // 'this' - means that you finding some child class from '.foobar-close-button-class'
              // '.child' -means that you finding child class with name '.foobar-close-button-child-class'
          });
          

          【讨论】:

            【解决方案10】:

            您可以使用 event.currentTarget。它只会在获得事件的元素中执行点击事件。

            target = e => {
                console.log(e.currentTarget);
              };
            <ul onClick={target} className="folder">
                  <li>
                    <p>
                      <i className="fas fa-folder" />
                    </p>
                  </li>
                </ul>

            【讨论】:

              【解决方案11】:

              // if its li get value 
              document.getElementById('li').addEventListener("click", function(e) {
                              if (e.target == this) {
                                  UodateNote(e.target.id);
                              }
                              })
                              
                              
                              function UodateNote(e) {
              
                  let nt_id = document.createElement("div");
                  // append container to duc.
                  document.body.appendChild(nt_id);
                  nt_id.id = "hi";
                  // get conatiner value . 
                  nt_id.innerHTML = e;
                  // body...
                  console.log(e);
              
              }
              li{
               cursor: pointer;
                  font-weight: bold;
                font-size: 20px;
                  position: relative;
                  width: 380px;
                  height: 80px;
                  background-color: silver;
                  justify-content: center;
                  align-items: center;
                  text-align: center;
                  margin-top: 0.5cm;
                  border: 2px solid purple;
                  border-radius: 12%;}
                  
                  p{
                   cursor: text;
                font-size: 16px;
                 font-weight: normal;
                  display: block;
                  max-width: 370px;
                  max-height: 40px;
                  overflow-x: hidden;}
              &lt;li id="li"&gt;&lt;p&gt;hi&lt;/p&gt;&lt;/li&gt;

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2018-04-30
                • 1970-01-01
                • 2012-05-09
                • 1970-01-01
                • 2010-09-28
                相关资源
                最近更新 更多