摧毁或移除Backbone.js中的视图

85

我目前正在尝试实现视图的销毁/移除方法,但我无法找到适用于所有视图的通用解决方案。

我希望能够将事件附加到控制器上,这样当一个新请求进来时,它可以销毁先前的视图然后加载新的视图。

有没有办法在不必为每个视图构建删除函数的情况下实现这一点?


你能举个例子说明你的视图生态系统是什么吗?你的问题让我想到页面上可能有很多视图同时存在。我无法准确地想象你试图做什么,因此无法提供可能符合你需求的答案。 - Bill Eisenhauer
1
从这些伟大的帖子中学到了一些其他的模式:http://lostechies.com/derickbailey/2011/09/15/zombies-run-managing-page-transitions-in-backbone-apps/ http://coenraets.org/blog/2012/01/backbone-js-lessons-learned-and-improved-sample-app/#comment-57351 - daedelus_j
7个回答

163

我必须绝对确定该视图不仅已从DOM中删除,而且还完全解除了事件绑定。

destroy_view: function() {

    // COMPLETELY UNBIND THE VIEW
    this.undelegateEvents();

    this.$el.removeData().unbind(); 

    // Remove view from DOM
    this.remove();  
    Backbone.View.prototype.remove.call(this);

}

对我来说,这似乎有点过度,但其他方法并没有完全解决问题。


10
根据我所看到的,this.remove() 应该调用 jQuery 的 remove 方法,它可以将元素从 DOM 中删除,同时还会删除与其关联的数据和事件。因此,我认为不需要调用 undelegateEvents 和 removeData 方法... 我的理解正确吗? - opensas
1
@opensas:尽管该元素已从DOM中删除,事件仍然持续存在,需要使用this.undelegateEvents()解除所有事件的绑定。就像我说的那样,这似乎有点过度,但它确实解决了问题。 - sdailey
3
我喜欢它。尽管你应该使用this.$el而不是$(this.el) ;) - mreq
3
对于我解决问题的好回答,加一赞。对于您写下的第一个答案,也加一赞 :) - 1nfiniti
1
我的视图在销毁并重新创建后没有被重新渲染。这是因为 this.remove() 的缘故吗? - Raeesaa
显示剩余8条评论

48

如果不知道所有的信息...你可以将重置触发器绑定到你的模型或控制器:

this.bind("reset", this.updateView);

当您想要重置视图时,触发重置操作。

对于您的回调函数,请执行以下操作:

updateView: function() {
  view.remove();
  view.render();
};

5
我认为这不正确。View的remove函数只是从DOM中删除该视图元素(在此处查看)。我认为这个人想要完全删除该视图对象。 - Nutritioustim
2
this.remove() 最终会调用 jQuery 的 remove() 方法,该方法还会删除数据和事件... 尽管如此,我认为您还需要调用 this.undelegateEvents 来解除绑定其他事件,例如自定义事件或对模型的更改。 - opensas
21
this.remove() 调用了 this.stopListening()this.$el.remove()。前者会移除所有通过 this.listenTo(...) 添加的事件监听器,后者会移除所有通过 jQuery 添加的事件监听器。使用这两个方法,你应该就可以涵盖大部分情况,除非你使用了其他方式添加事件监听器。因此,这个答案是正确的并且我会给它一个 +1。 - chowey

20

我知道我来晚了,但希望这对其他人有用。如果你正在使用backbone v0.9.9 +,可以使用listenTostopListening

initialize: function () {
    this.listenTo(this.model, 'change', this.render);
    this.listenTo(this.model, 'destroy', this.remove);
}

stopListening 方法会被 remove 方法自动调用。你可以在这里这里阅读更多相关内容。


8

这是我一直在使用的。没有发现任何问题。

destroy: function(){
  this.remove();
  this.unbind();
}

4

根据当前 Backbone 的文档...

view.remove()

从 DOM 中移除一个视图和它的 el,并调用 stopListening 方法来删除该视图已经监听 (listenTo'd) 的所有绑定事件。


0

我认为这应该可以工作

destroyView : function () {
    this.$el.remove();
}

必须使用 this.stopListening() 来终止监听器,然后为了保险起见,加上 return this - Brandon

0

你可以使用这种方法来解决问题!

initialize:function(){
    this.trigger('remove-compnents-cart');
    var _this = this;
    Backbone.View.prototype.on('remove-compnents-cart',function(){
        //Backbone.View.prototype.remove;
        Backbone.View.prototype.off();
        _this.undelegateEvents();
    })
}

另一种方法:创建一个全局变量,像这样:_global.routerList
initialize:function(){
    this.routerName = 'home';
    _global.routerList.push(this);
}
/*remove it in memory*/
for (var i=0;i<_global.routerList.length;i++){
    Backbone.View.prototype.remove.call(_global.routerList[i]);
}

第一种方法对我有效,但我遇到了类似的视图幽灵问题,每当重新创建每个视图时,事件都会多次触发,当您提交表单时。 - ONYX

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接