1

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

问题是某人第二次返回主屏幕并再次执行此操作,这次每个按钮都有两个事件。第三次有三个事件。很明显原来的视图还在听这些按钮。我已经阅读了这个并调用了 Remove() 方法,但这是我需要做的吗?如果是这样,我在哪里调用删除?相关代码如下:

第一个视图

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;
    }   
});
4

3 回答 3

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();
  }

});
于 2013-09-10T18:07:58.890 回答
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超出路由器范围的情况下制作它。

于 2014-10-11T08:07:38.570 回答
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 方法中添加 empty 方法

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

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

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

于 2013-09-10T17:57:59.207 回答