旧的骨干视图导致额外的事件触发器

时间:2013-09-10 17:09:13

标签: javascript backbone.js

好的,我已经对此做了一些阅读,我很确定我知道问题与我有什么关系我只是不知道修复它的最佳方法。我有标准的骨干路由器为我设置项目详细信息视图,然后当我点击一个名为“开始”的按钮时,它创建了一个新视图,它带我进入一种人们可以用一些按钮玩的游戏在底部附加了“点击”事件。第二个视图不是通过路由器调用,而是直接从第一个视图调用。

问题是有人第二次回到主屏幕并再次进行,这次每个按钮都附加了两个事件。第三次有三个事件。显然原始视图仍在听这些按钮。我已经读过这个并调用Remove()方法,但这是我需要做的吗?如果是这样我在哪里打电话删除?相关守则如下:

1ST VIEW

window.GameDrillView = Backbone.View.extend({

    initialize: function () {
        this.render();
    },

    render: function () {
        $(this.el).html(this.template(this.model.toJSON()));
        return this;
    },

    events: {
        "click .start" : "startGameDrill",
    },


 startGameDrill: function () {
  var start = $('#start').val();.
  var stop = $('#stop').val();.
   var StartView = new GameDrillStartView({model: this.model, el: $('#content')[0], start: start, stop:stop});

}

});

开始观看

window.GameDrillStartView = Backbone.View.extend({

   // declare variables
    initialize: function () {
    this.render();
    },

        events: {
            "click .nextstage"   : "nextstage",  // 2ND TIME THROUGH GETS CALLED TWICE

        },

 nextstage: function () {

      // Do some stuff // 

      this.render(); //Re-render
},

    render: function () {

       // Do some variables stuff

      this.$el.html(this.template(jQuery.extend(this.model.toJSON(), extended_options)));..
        return this;
    }   
});

3 个答案:

答案 0 :(得分:1)

更改视图时,您需要从undelegateEvents()调用Backbone.View方法。它禁用侦听events { }块中提到的所有元素事件。此外,如果您需要销毁旧视图,则可以调用视图的remove()方法,该方法将在内部调用undelegateEvents()

更新(来自官方网站的示例)

var Workspace = Backbone.Router.extend({

  routes: {
    "help":                 "help",    // #help
    "search/:query":        "search",  // #search/kiwis
    "search/:query/p:page": "search"   // #search/kiwis/p7
  },

  help: function() {
    if (this.currentView)
       this.currentView.undelegateEvents();

    this.currentView = new HelpView();
  },

  search: function(query, page) {
    if (this.currentView)
       this.currentView.undelegateEvents();

    this.currentView = new SearchView();
  }

});

答案 1 :(得分:0)

一个选项是只创建一个视图实例:

if(_.isUndefined(this.StartView))
    this.StartView = new GameDrillStartView({model: this.model, el: $('#content')[0], start: start, stop:stop});
else
    this.StartView.render();

在GameDrillStartView的render方法中添加空方法

this.$el.html(this.template(jQuery.extend(this.model.toJSON(), extended_options)))

通过这种方式,您不会添加更多事件侦听器,但每次用户按下按钮时都会更新页面。

您可以在GameDrillView中管理StartView的生命周期,因为它似乎是一个更好的地方。

答案 2 :(得分:0)

遇到同样的麻烦。凌乱的解决方案:

var current_view = false;
var prev_view = false;
var AppRouter = Backbone.Router.extend({
    routes: {
        "events/:id": "viewEvent",
    }
});

var app_router = new AppRouter;

app_router.on('route:viewEvent', function (event_id) {
    var _event = new Event({id:event_id});
    current_view = new EventView({ 
        model: _event, 
    });
});

//Will be called after route:viewEvent
app_router.on('route', function () { 
    if(prev_view) {
        prev_view.undelegateEvents();
    }
    prev_view = current_view;
});

不确定如何在没有current_viewprev_view的情况下使用它。