删除和取消绑定主干中的子视图
Remove and unbind subviews in Backbone
我正在使用Backbone 1.1.2,我发现我的应用程序的一些奇怪行为可能是由于zombieviews。我读了Derick Bailey的文章"Run!Zombies!",但后来发现这是为旧版本的Backbone写的(如果我是对的,0.9)。
然后我发现,对于较新的Backbone版本,对视图执行.remove()就足够了,可以正确地杀死它们(因为与ListenTo绑定的事件将通过调用StopListening自动删除)。
在我的应用程序中,我有一个全局视图,在某个时刻会创建两个子视图。当单击重置按钮(在全局视图中)时,应该重新绘制这些视图(但可能首先删除/解除绑定以防止僵尸视频)。
因此,我所做的是将子视图附加到全局视图可以访问的列表中。在初始化功能中:
this._views = []; // empty list
当呈现子视图时,我将它们添加到列表中
v = new app.gameView();
this._views.push(v);
就在重新绘制子视图之前,我调用了一个函数cleanUp,该函数循环遍历子视图列表,并对每个子视图执行.remove()和.unbind():
_.each(this._views, function(view){
this.remove();
this.unbind();
});
this._views = []; // empty the list for next use
我的问题有两个:
- 调用.remove和.unbind是否足以阻止zombieviews
- 将子视图添加到全局视图中的列表中是正确的方法吗
感谢您的任何想法!
根据我的经验,简单地调用remove()
和unbind()/off()
就足以防止"僵尸"四处游荡。我要补充的唯一一点是,如果父视图(包含this._views
内部子视图的父视图)是从应用程序的另一部分引用的,那么您必须确保通过将这些变量赋值为null来删除这些引用。
在父级中有一个this._views
数组来保存其子视图是完全可以的。但是,随着应用程序的发展,您可能需要创建某种子视图管理器和所有其他视图都继承的核心视图。
以下是我过去所做的事情;我希望它能有所帮助:
CoreView:
// Probably all views should inherit from CoreView.
define([
'jquery',
'backbone',
'subviews'
], function($, Backbone, Subviews) {
var CoreView = Backbone.View.extend({
$main: $('#main'),
// Create an empty `subviews` property on all views.
constructor: function() {
this.subviews = new Subviews(this);
// Since we're overriding `constructor` here,
// we need to delegate to Backbone
Backbone.View.prototype.constructor.apply(this, arguments);
},
// Views should be attached to the DOM only with the `attach` method to have the right events thrown.
// Attach the view's element only if it's not already in the DOM.
attach: function() {
if (!this.isAttached()) {
this.$main.append(this.el);
this.trigger('dom:attach');
}
return this;
},
isAttached: function() {
return $.contains(document.body, this.el);
},
// Remove each view's subviews and clean up various properties before
// calling Backbone's remove() method.
remove: function() {
if (this.subviews.size()) {
this.subviews.removeAll();
}
// Remove the DOM element (jQuery makes sure to clean up DOM element's data)
Backbone.View.prototype.remove.apply(this, arguments);
// Fire a helpful `dom:detach` event when the view is removed from the DOM.
this.trigger('dom:detach');
this.off();
return this;
}
});
return CoreView;
});
子视图管理器(未完成):
// Simple Subview Manager
define([
'jquery',
'backbone'
], function($, Backbone) {
function Subviews(view) {
this.self = view; // this view
this._entries = {}; // its subviews
}
Subviews.prototype = {
constructor: Subviews,
add: function(name, viewInstance) { ... },
has: function(name) { return !!this._entries[name]; },
get: function(name) { return this._entries[name] && this._entries[name]; },
// By default the subview manager tries to replace an element with
// a `data-subview` attribute with the actual subview element.
attach: function(name) {
// In the parent view's template you would have: `<div data-subview="child1"></div>`
var $subViewOutput = this.self.$('[data-subview="'+name+'"]');
if (this._entries[name] && $subViewOutput.length) {
$subViewOutput.replaceWith(this._entries[name].render().el);
}
},
// When removing a subview we also have to remove it from
// this view's `subviews` property.
remove: function(name) {
if (this._entries && this._entries[name]) {
this._entries[name].remove();
// Cleanup
this._entries[name] = null;
this._entries = _.omit(this._entries, name);
}
},
removeAll: function() {
if (this.size()) {
_.each(this._entries, function(view) {
view.remove(); // it will call remove() in CoreView first
});
}
this._entries = {};
this.self = null;
},
size: function() {
return _.size(this._entries);
}
};
return Subviews;
});
普通视图:
define([
'jquery',
'backbone',
'templates',
'views/coreView',
'views/childView'
],
function($, Backbone, templates, CoreView, ChildView) {
var Widget = CoreView.extend({
tagName: 'section',
id: 'widget123',
template: templates.widget123,
initialize: function() {
this.subviews.add('child1', new ChildView());
this.on('dom:attach', function() {
// When the parent is inserted into the DOM also insert its child1
this.subviews.attach('child1');
});
},
render: function() {
this.$el.html(this.template());
return this;
}
});
var instance = new Widget();
instance.render().attach(); // attach() comes from CoreView
});
- 取消绑定主干视图事件
- 取消选择滚动启动时的所有列表视图项目
- 如何选中/取消选中外部按钮的网格视图复选框
- 收听单选按钮取消选择事件而不知道按钮's上下文(骨干视图)
- 在删除视图时取消所有传出的REST HTTP请求
- 删除和取消绑定主干中的子视图
- 使用转义键在余烬文本视图中取消操作
- ASP.net VB 详细信息视图插入:取消问题的 javascript 回发
- Javascript 选中/取消选中树视图的所有按钮
- 从模型中取消视图的绑定
- 主干 - 在模型更改时取消注册视图事件
- 不再需要视图后取消委派事件的最佳方法
- 详细信息视图 ASP.Net 取消客户端的默认编辑模式
- 树视图,选中全部或取消选中全部在挖空.js
- 主干 - 绑定和取消绑定当前视图上的事件
- 如何测试Backbone.js视图是否正确地取消绑定()和destroyed()
- 在setElement上取消委派子视图事件
- 如果关闭了模态弹出窗口而没有取消在模态内的网格视图中的行编辑,则它不会再次打开
- 不能在主干视图中取消对象的字符串化
- Dojo MVC:如何在数据错误时取消视图转换