jQuery :not() 选择器在 .off() 方法中不起作用

jQuery :not() selector does not work in .off() methode

为什么 .off() 方法中的 :not():has() 选择器没有得到完全支持?

$(document).off() 取消绑定文档中的所有事件。

$(document).off('.MyNamspace') 取消绑定使用命名空间 'MyNamspace' 创建的所有事件,例如$(document).on('click.MyNamespace','a',function(){})

但是

$(document).off(':not(.MyNamspace)')returns正则表达式错误

以后可以实现吗?

问题更详细:

假设我有一个 HTML 基础框架,例如导航栏和一些事件将其与定义的限定符绑定在一起。在这个框架中是一个容器,它包含可变内容和动态加载 JavaScript 并且还在动态加载容器中的元素上绑定事件。

如果内容发生变化,我还想删除关联的 JavaScript 部分和所有事件,除了我自己为框架创建的(和其他类似引导事件)。

动态加载的JavaScript严格加载到一个对象中,如:

foo = new whatEverYouWant();

当容器的内容将被其他内容替换时,我将 foo 设置为 undefined 或 null,所有定义的变量和方法都消失了。

但是如果用户分配了一个事件,例如:

$(document).on('mousemove', function(e) {
  console.lg(e,'bla bla bla');
});

删除内容后活动继续

正如您在 JQuery API Documentation 上看到的,您不能在事件参数上使用选择器

.off( events [, selector ] [, handler ] )

events Type: String One or more space-separated event types and optional namespaces, or just namespaces, such as "click", "keydown.myPlugin", or ".myPlugin".

你做

.off([ selector ])

所以你必须做

$(document).off('events ','[selector]')

过滤命名空间没有神奇的方法。

但是您可以使用 $._data(element,'events').

访问分配给元素的所有 jQuery 事件

返回的对象使用 eventName 作为键,每个键包含一个对象数组,这些对象包含 namespaceselector 等属性。

然后您可以迭代各种事件并执行类似操作:

/**
 * @param {DomNode} element - Element to remove namespaced events from.
 * @param {array} keepNamespaces - Array of namespaces not to remove.
 */
function removeOtherNameSpaces(element, keepNamespaces) {
  var events = $._data(element, 'events'),
      $el = $(element);
  
  $.each(events , function(eventName, arr) {    
    $.each(arr, function(_, obj) {
      if (!obj) return;

      if (obj.namespace && $.inArray(obj.namespace, keepNamespaces) === -1) {
        console.log('Removed:: Event:',eventName,', namespace: ', obj.namespace)
        $el.off('.' + obj.namespace);
      }
    });
  });
}

// DEMO
$(document).on('click.click-1', 'p', function() {
  console.log('Namespace: click-1 triggered')
}).on('click.click-2', 'p', function() {
  console.log('Namespace: click-2 triggered')
}).on('mouseenter.mouse-1', 'p', function() {
  console.log('Namespace: mouse-1 triggered')
})

$('button').click(function() {
  var keepNamespaces = ['click-1'];
  removeOtherNameSpaces(document, keepNamespaces)
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>
  Hover & Click me - before click button
</p>
<button>
  Remove namespace events
</button>

这也可以扩展为仅从特定的委托目标选择器中删除事件