【问题标题】:Am I binding events over and over again in this jQuery code?我是否在这个 jQuery 代码中一遍又一遍地绑定事件?
【发布时间】:2013-02-04 04:40:34
【问题描述】:

所以我使用了这个totally awesome tool called Visual Event,它显示了绑定到一个对象的所有事件处理程序 - 我注意到每次我单击或玩弄我的对象并检查绑定到它的事件处理程序列表时,都有和每次更多。我的问题是这个:console.trace or stack trace to pinpiont the source of a bug in javascript? 在使用 Visual Event 和其他人的建议之后,我想我的问题是我可能一遍又一遍地将相同的处理程序绑定到相同的事件。有没有办法定期解除绑定?

我的应用程序有一堆插件连接到动态创建的divs。这些divs 可以调整大小并在各处移动。该应用程序是一种编辑器,因此用户可以在他们喜欢的任何设计中排列这些 div(包含图像或文本)。如果用户单击一个 div,它就会“激活”,而页面上的所有其他 div 都会“停用”。我有一堆相关的插件,比如activateTextBoxinitTextBoxdeactivateTextBoxreadyTextBox等等。每当第一次创建 div 时,都会调用一次 init 插件,这只是创建后的第一次,如下所示:

$(mydiv).initTextBox();

但是 readyTextBoxactivateTextBoxdeactivateTextBox 经常被调用,具体取决于其他用户事件。

init 中,我首先使用resizable()draggable() 之类的绑定内容,然后将框“准备好”以供使用

    $.fn.extend({
        initTextBox: function(){
        return this.each(function() {
               // lots of code that's irrelevant to this question
               $this.mouseenter(function(){ 
        if(!$this.hasClass('activated'))
            $this.readyTextBox();
         }
         $this.mouseleave(function(){ 
        if($this.hasClass('ready')){
            $this.deactivateTextBox(); 
                    $this.click(function(e){
                 e.preventDefault();
                 });
                }
             });
     }); 
  });

这是readyTextBox 插件的简化摘要版本:

(function($){
    $.fn.extend({
        readyTextBox: function(){
        return this.each(function() {
               // lots of code that's irrelevant to this question
               $this.resizable({ handles: 'all', alsoResize: img_id});
               $this.draggable('enable');
               $this.on( "dragstop", function( event, ui )
               {/* some function */ });
               $this.on("resizestop", function( event, ui ){ /* another function */ });
               // and so on
});

然后是activateTextBox()

    $.fn.extend({
        activateTextBox: function(){
        return this.each(function() {
               // lots of code that's irrelevant to this question
               $this.resizable('option','disabled',true); //switch of resize & drag
               $this.draggable('option', 'disabled', true);
});

然后deactivate,我再次打开可拖动和调整大小,使用代码:

$this.draggable('enable'); $this.resizable('option','disabled',false);

这些 div 或“文本框”包含在一个更大的名为 content 的 div 中,这是我在 content 中的点击代码:

$content.click(function(e){
    //some irrelevant code
     if( /* condition to decide if a textbox is clicked */) 
     {  $(".textbox").each(function(){ //deactivate all except this
        if($(this).attr('id') != $eparent.attr('id')) 
            $(this).deactivateTextBox();
        });
        // now activate this particular textbox
        $eparent.activateTextBox();
             }
          });

这几乎是与文本框相关的相关代码。为什么每当我拖动某些东西然后检查 Visual Event 时,点击次数、拖动停止次数和鼠标悬停次数都比以前多?此外,用户与页面交互的次数越多,事件完成所需的时间就越长。例如,我从 div 鼠标移出,但 move 光标需要 loooong 时间才能恢复默认值。我停止拖动,但在准备好接受更多用户点击之前,一切都卡住了一段时间,等等。所以我猜问题必须是我将太多东西绑定到相同的事件需要在某些时候解除绑定观点?它变得如此糟糕,以至于 draggable 最终会在某个时候停止工作。文本框卡住了 - 它们仍然可以调整大小,但拖动停止工作。

【问题讨论】:

    标签: javascript jquery jquery-ui binding event-handling


    【解决方案1】:

    我是否一遍又一遍地绑定事件

    是的。看看你的代码:

    $this.mouseenter(function(){ 
        …
        $this.mouseleave(function(){ 
            …
            $this.click(function(e){
                …
            });
        });
    });
    

    这意味着每次将鼠标悬停在元素上时,都会添加另一个离开处理程序。当你离开元素时,每个处理程序都会添加另一个点击事件。

    我不确定你想做什么,但有几种选择:

    • 仅绑定一次事件处理程序,并使用布尔变量等跟踪当前状态。
    • 在绑定之前,删除所有其他已绑定的事件处理程序。 jQuery 的event namespacing 可以帮助您仅删除您自己的插件添加的那些。
    • 使用one() method,它会在触发侦听器后自动解除绑定。

    【讨论】:

    • 但是initTextBox() 只被调用一次,第一次。那么如何编写第一个绑定呢?还是最好做类似if(!bound(this.mouseleave)){//only then do the binding //}(伪代码)
    猜你喜欢
    • 1970-01-01
    • 2017-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多