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

Álv*_*lez 4 javascript jquery css-selectors

:not()选择器让我很困惑.在简单的CSS中似乎相当简单:

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

但是,当应用于过滤触发事件的所选元素的后代时,我无法掌握逻辑:

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);
  });
});
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

这种方式背后的理由是什么:not()

我真的在寻找一个解释,而不是修复.

Cer*_*nce 5

问题在于keydown事件起泡input.如果使用:not(input),当事件刚刚在input元素处初始化时,处理程序将不会触发,但是当事件冒泡到元素时它将触发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);
  });
});
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

如果你继续添加:nots,你会看到它一直冒泡到HTML标签:

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);
  });
});
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

我想你可以使用:not(input):not(section):not(body):not(html),但这有点愚蠢而难以管理.

你的第三个处理程序正确地排除了input触发事件,但只有 input(和类似的)元素触发keydown事件 - 例如,它不能从a中触发<section>.如果有一个textarea子节点section和输入可能会更清楚- 你会看到textarea触发处理程序,但输入不是:

$(document).on("keydown", "section :not(input)", function(event) {
  console.log("Event handler #3 on", event.target);
});
Run Code Online (Sandbox Code Playgroud)
<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">
  <textarea></textarea>
</section>
Run Code Online (Sandbox Code Playgroud)