如何仅在事件处理程序尚不存在时才绑定它?



我有一个要将拖放事件绑定到的页面。我希望浏览器中的整个页面都是拖放目标,因此我已将事件绑定到document对象。不过,我的应用程序的内容是通过AJAX加载到主内容区域的,我只希望这些事件处理程序在上传页面当前可见时处于活动状态。

现在,当检索上传页面时,我正在绑定事件处理程序;但是,每次上传页面变为活动时,它都会绑定一个新的事件处理程序,这会导致当用户转到上传页面、离开然后返回时,处理程序会多次触发。我在想,如果我能让处理程序仅在尚未绑定时绑定,我就能解决这个问题。这可能吗,还是我忽略了一个更好的选择?

相关代码,如果有帮助:

$(document).bind('dragenter', function(e) {
    e.stopPropagation();
    e.preventDefault();
}).bind('dragover', function(e) {
    e.stopPropagation();
    e.preventDefault();
}).bind('drop', function(e) {
    e.stopPropagation();
    e.preventDefault();
    self._handleFileSelections(e.originalEvent.dataTransfer.files);
});

在绑定新的事件处理程序之前,先取消绑定现有的事件处理。这对于命名空间事件[docs]:来说非常简单

$(document)
  .off('.upload') // remove all events in namespace upload
  .on({
      'dragenter.upload': function(e) {
          e.stopPropagation();
          e.preventDefault();
      },
      'dragover.upload': function(e) {
          e.stopPropagation();
          e.preventDefault();
      },
      // ...
  });

对于那些只想添加一次事件的人,避免对每个新克隆的元素使用unbind()/off()bind()/on()方法。

我在代码项目网站上发现了一篇文章"用JQuery将事件绑定到尚未添加的DOM元素(作者Khrystyna Popadyuk)",该文章展示了如何只注册一次事件,甚至在元素存在之前。详细信息请阅读他的文章全文。

$("body").on("click", ".your-style", function(event) {
       // your code ...
});

我写了一个"uon";(唯一的)执行此操作的jquery扩展:

$.fn.extend({
    uon:function(eventname,fn) {
        this.each(function() {
            var alreadyexists=false;
            var exevby=$._data(this,'events');
            for(var xevn in exevby) {
                if(xevn==eventname) {
                    exevby[xevn].forEach(evobj=>{
                        if(evobj.handler==fn) alreadyexists=true;
                    });
                }
            }
            if(!alreadyexists) $(this).on(eventname,fn);
        });
    }
});

这意味着你可以说:

$(this).uon('click',doSomething);
$(this).uon('click',doSomething);
$(this).uon('click',doSomething);

点击时它只会做一次Something,而不是3次。

它特别适合这个对象:

var JQEvent={
    ons:[],
    onload:function(sel,fn) {
        JQEvent.ons.push({sel:sel,fn:fn});
    },
    apply:function($el) {
        JQEvent.ons.forEach(on => {
            $el.find(on.sel).each(on.fn);
        });
    }
}

这意味着你可以说

JQEvent.onload('input.field',function() {
   $(this).uon('click',doSomething);
}

当你点击一个input.field时,你可能想在整个系统中做点什么。

然后,当你在javascript中动态加载一些HTML或构建一些dom元素时,你就可以应用通用的:

JQuery.apply('div.new-container-element');

该元素的任何子div都将应用这些函数。

相关内容

  • 没有找到相关文章