javascript 多次触发骨干绑定事件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11202707/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 12:22:44  来源:igfitidea点击:

Backbone bind event fired multiple times

javascriptbackbone.js

提问by TonyTakeshi

I am trying to build a switching view with backbone js and found out my bind event fired multiple times, when I switching view for few times.

我正在尝试使用主干 js 构建切换视图,当我切换视图几次时,我发现绑定事件多次触发。

Below is the code for better illustration:

下面是更好地说明的代码:

html

html

<div id='container'>
    halo world
</div>

<button id='but1'>red view</button>
<button id='but2'>blue view</button>

css

css

#red_view{
    width:400px;
    height:400px;
    background-color:red;        
}
#blue_view{
    width:400px;
    height:400px;
    background-color:blue;        
}
.button,.button2{
    width:300px;
    height:300px;
    background-color:gray;
}

? javascript

? javascript

RedView = Backbone.View.extend({
    el: "#container",
    events:{"click .button":"clickme"},
    clickme:function(){
        alert('redview');                        
    },
    initialize: function(){
        this.$el.html("<div id='red_view'><div class='button'>Click Me</div></div>");            
    }
});

BlueView = Backbone.View.extend({
    el: "#container",
    events:{"click .button2":"clickme2"},
    clickme2:function(){
        alert('blueview');                        
    },    
    initialize: function(){
        this.$el.html("<div id='blue_view'><div class='button2'>Click Me</div></div>");            
    }
});

$(document).ready(function(){
    //var router = new SystemRouter();

    $('#but1').click(function(){
       var view = new RedView();
    });
    $('#but2').click(function(){
       var view = new BlueView();
    });    
});

If you click the red view for 3 times, and press 'click me'. It will pops up alert for 3 times as well. I suspect there's need to unbind the event somewhere, but couldn't find proper way to do it. Best to provide some references of doing this correctly.

如果您单击红色视图 3 次,然后按“单击我”。它也会弹出3次警报。我怀疑需要在某处解除绑定事件,但找不到合适的方法来做到这一点。最好提供一些正确执行此操作的参考。

?Here's the link to jsfiddle demo. http://jsfiddle.net/mochatony/DwRRk/31/

?这是 jsfiddle 演示的链接。http://jsfiddle.net/mochatony/DwRRk/31/

回答by jakee

Every time you click the red viewor blue view-buttons you create a new Red or Blue View each and every time. You bind their events hash to respond to click DOM events originating from buttons with classes buttonand button2.

每次单击red viewblue view按钮时,都会创建一个新的红色或蓝色视图。您绑定它们的事件散列以响应源自带有类button和 的按钮的单击 DOM 事件button2

  1. Press 'red view' 3 times -> 3 instances of RedView created
  2. Click button with class 'button' -> DOM event
  3. 3 instances of RedView listening to said DOM event -> 3 alerts
  1. 按“红色视图”3 次 -> 创建了 3 个 RedView 实例
  2. 单击带有“按钮”类的按钮 -> DOM 事件
  3. 3 个 RedView 实例监听 DOM 事件 -> 3 个警报

This is because you don't clean the views before creating a new one effectively leaving you with ghost views that respond to events even though they can't be seen. (More info on the events hash)You can clean the events from you views with something like this.

这是因为您在创建新视图之前没有清理视图,有效地留下了对事件做出响应的幽灵视图,即使它们无法被看到。(有关事件哈希的更多信息)您可以使用类似的方法清除视图中的事件。

cleanup: function() {
  this.undelegateEvents();
  $(this.el).clear();
}

Here is your fiddle with working cleanup of views http://jsfiddle.net/DwRRk/34/

这是你的工作清理视图http://jsfiddle.net/DwRRk/34/

Also a hint for good practice: you should use something like a render method to attach stuff to your DOM, use the initialize to just initialize the needed values for your view.

还有一个良好实践的提示:您应该使用类似渲染方法的东西将内容附加到您的 DOM,使用 initialize 来初始化您的视图所需的值。

回答by Esailija

You are creating a new view everytime the buttons are clicked, without destroying the previous one. Try using a single view likes this:

每次单击按钮时,您都在创建一个新视图,而不会破坏前一个视图。尝试使用像这样的单一视图:

http://jsfiddle.net/DwRRk/32/

http://jsfiddle.net/DwRRk/32/

var SomeModel = Backbone.Model.extend({});

var SomeView = Backbone.View.extend({
    el: "#container",
    model: SomeModel,
    events: {
        "click .button": "clickme"
    },
    clickme: function() {
        alert(this.model.get("color"));
    },
    colorChanged: function() {
        this.$el.html("<div id='" + this.model.get("color") + "_view'><div class='button'>Click Me</div></div>");
    },

    initialize: function() {
        _.bindAll( this, "colorChanged" );
        this.model.on("change:color", this.colorChanged );
        this.model.on("reset", this.colorChanged );
    }
});



$(document).ready(function() {
    //var router = new SystemRouter();
    var model = new SomeModel({color: "red"}),
        view = new SomeView({model: model})


    $('#but1').click(function() {
        model.set("color", "red");
    });
    $('#but2').click(function() {
        model.set("color", "blue");
    });
});?

回答by Barry

Here's another way of deleting ghost views(what i'm using)

这是删除幽灵视图的另一种方法(我正在使用)

disposeView: function(view){
   Backbone.View.prototype.close = function () {
      this.unbind();
      this.undelegateEvents();
   };

   /* --Destroy current view */
   if(this.currentView !== undefined) {
      this.currentView.close();
   }

   /* --Create new view */
   this.currentView = view;
   this.currentView.delegateEvents();

   return this.currentView;
}

disposeView(new view());

Be sure to always return "this" in your view or else this won't work.

确保始终在您的视图中返回“this”,否则这将不起作用。