jQuery - *:not() 不排除元素

jQuery - *:not() not excluding elements

我的目标是在 <kbd><textarea> 标签以外的所有地方禁用右键单击。我正在使用 *:not(kbd,textarea) 来排除禁用右键单击 - .on('contextmenu', function(e){ e.preventDefault(); });。我应该可以右键单击 <kbd><textarea> 标签,但我不能。很奇怪。

$(document).ready(function(){
  $('*:not(kbd,textarea)').on('contextmenu', function(e){
      e.preventDefault();
  });
});
div {
  width: 170px;
  height: 170px;
  background-color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<kbd>right click me</kbd>
<textarea>right click me</textarea>
can't right click me
</div>

明确一点:*:not(kbd,textarea) 工作正常。问题与浏览器中事件的处理方式有关。

大多数事件都会冒泡,contextmenu does as well。由于 <kbd><textarea> 元素位于 <div> 内,因此绑定到 <div> 的事件处理程序将始终取消 contextmenu 事件。

根据您的确切用例,您可以简单地检查事件是否起源于元素本身,并仅在这种情况下阻止它:

$(document).ready(function(){
  $('*:not(kbd,textarea)').on('contextmenu', function(e){
      if (this === e.target) {
        e.preventDefault();
      }
  });
});
div {
  width: 170px;
  height: 170px;
  background-color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<kbd>right click me</kbd>
<textarea>right click me</textarea>
can't right click me
</div>


但是,不要将处理程序绑定到每个元素,而是使用事件委托。将处理程序绑定到文档的根目录并检查事件的来源:

$(document).ready(function(){
  $('body').on('contextmenu', function(e){
      if (!$(e.target).is('kbd,textarea')) {
        e.preventDefault();
      }
  });
});
div {
  width: 170px;
  height: 170px;
  background-color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<kbd>right click me</kbd>
<textarea>right click me</textarea>
can't right click me
</div>