使用:not()过滤掉事件处理程序中的元素

时间:2018-12-13 08:27:20

标签: javascript jquery css-selectors

:not() selector使我很困惑。简而言之,CSS似乎很简单:

section { /* Overriden as expected */
  color: red;
}
input {
  color: green; /* In effect as expected */
}
:not(input) {
  color: blue; /* In effect as expected */
}
<section>
  <p>Lorem ipsum</p>
  <input value="Lorem ipsum">
</section>

但是,当用于过滤触发事件的选定元素的后代时,我无法理解逻辑:

jQuery(function($){
  $(document).on("keydown", "input", function(event){
    // This fires only for <input> as expected
    console.log("Event handler #1 on", event.target);
  });  

  $(document).on("keydown", ":not(input)", function(event){
    // This fires for *all* elements :-?
    console.log("Event handler #2 on", event.target);
    // ... even though these checks return the results that intuition suggests
    console.log('Is "input"? %s; Is ":not(input)"? %s',
      $(event.target).is("input"),
      $(event.target).is(":not(input)")
    );
  });

  $(document).on("keydown", "section :not(input)", function(event){
    // This *never* fires :-?
    console.log("Event handler #3 on", event.target);
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<section>
  <p>Click and type here</p>
  <input value="Click and type here">
</section>

:not()在这里工作的原理是什么?

我实际上是在寻找一种解释,而不是一种解决方法。

1 个答案:

答案 0 :(得分:5)

问题是keydown事件从input起泡。如果您使用:not(input),则事件仅在input元素上初始化时,处理程序将不会触发,但是当事件起泡到{{1 }}元素。您可以通过检查函数内部的section进行检查,该函数将引用处理程序触发时事件已冒泡的元素。 (当您在输入字段中键入内容时,this始终为event.target

input
jQuery(function($){
  $(document).on("keydown", ":not(input)", function(event){
    // This fires for *all* elements :-?
    console.log("Event handler #2 on", this);
  });
});

如果继续添加<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <section> <p>Click and type here</p> <input value="Click and type here"> </section>,则会看到它一直冒到HTML标签:

:not
jQuery(function($){
  $(document).on("keydown", ":not(input):not(section):not(body)", function(event){
    // This fires for *all* elements :-?
    console.log("Event handler #2 on", this);
  });
});

我想你可以使用<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <section> <p>Click and type here</p> <input value="Click and type here"> </section>,但这有点愚蠢且难以管理。

您的第三个处理程序正确地从触发事件中排除了:not(input):not(section):not(body):not(html),但是只有 input(和类似的元素)会触发input事件-它可以例如,不会从keydown触发。可能更清楚是否有<section>的textarea子项以及输入-您会看到textarea触发了处理程序,但是输入却没有:

section
$(document).on("keydown", "section :not(input)", function(event) {
  console.log("Event handler #3 on", event.target);
});

相关问题