use*_*232 64 javascript backbone.js
在不需要时处理模型/视图实例的最有效方法是什么?
通常,我将所有逻辑放在控制器/路由器中.决定应该创建哪些视图,以及应该为它们提供哪些模型.通常,有一些处理函数,对应于不同的用户操作或路由,每次执行处理程序时我都会创建新的视图实例.当然,这应该消除我以前存储在视图实例中的任何内容.但是,在某些情况下,某些视图会自行保留DOM事件处理程序,并且它们不会正确地解除绑定,从而导致这些实例保持活动状态.我希望有一种正确的方法来销毁视图实例,例如当他们的el(DOM表示)被分离或抛出DOM时
Der*_*ley 77
你正走在正确的道路上.您应该有一个控制视图生命周期的对象.我不喜欢把它放在我看来.我想为此创建一个单独的对象.
你需要做的事情是在必要时解开事件.要做到这一点,最好在所有视图上创建一个"close"方法,并使用控制所有内容生命周期的对象来始终调用close方法.
例如:
function AppController(){
this.showView = function (view){
if (this.currentView){
this.currentView.close();
}
this.currentView = view;
this.currentView.render();
$("#someElement").html(this.currentView.el);
}
}
Run Code Online (Sandbox Code Playgroud)
此时,您将代码设置为只有一个AppController实例,并且您始终可以appController.showView(...)从路由器或需要在#someElement屏幕部分显示视图的任何其他代码进行调用.
(我有一个非常简单的主干应用程序的另一个例子,它使用"AppView"(运行应用程序主要部分的主干视图),这里:http://jsfiddle.net/derickbailey/dHrXv/9/)
close默认情况下,该方法在视图上不存在,因此您需要自己为每个视图创建一个方法.在close方法中应该总是有两件事:this.unbind()和this.remove().除了这些,如果您将视图绑定到任何模型或集合事件,您应该在close方法中取消绑定它们.
例如:
MyView = Backbone.View.extend({
initialize: function(){
this.model.bind("change", this.modelChanged, this);
},
modelChanged: function(){
// ... do stuff here
},
close: function(){
this.remove();
this.unbind();
this.model.unbind("change", this.modelChanged);
}
});
Run Code Online (Sandbox Code Playgroud)
这将正确清理DOM中的所有事件(通过this.remove()),视图本身可能引发的所有事件(通过this.unbind())以及视图从模型中绑定的事件(通过this.model.unbind(...)).
Sha*_*ssy 13
简化方法是在Backbone.View对象上添加自定义关闭方法
Backbone.View.prototype.close = function () {
this.$el.empty();
this.unbind();
};
Run Code Online (Sandbox Code Playgroud)
使用上面的代码,您可以执行以下操作
var myView = new MyView();
myView.close();
Run Code Online (Sandbox Code Playgroud)
十分简单.
我总是在观察视角,有时重复使用模型.如果您保留模型,确保视图被取消分配可能会很痛苦.如果视图未正确绑定,模型可以保留对视图的引用.
从Backbone~0.9.9开始,使用view.listenTo()而不是model.on()的绑定模型允许通过控制反转(视图控制绑定而不是模型)更容易清理.如果使用view.listenTo()进行绑定,则对view.stopListening()或view.remove()的调用将删除所有绑定.与调用model.off(null,null,this)类似.
我喜欢通过使用close函数扩展视图来清理视图,该函数半自动调用子视图.子视图必须由父级的属性引用,或者必须将它们添加到名为childViews []的父级中的数组中.
这是我使用的关闭功能..
// fired by the router, signals the destruct event within top view and
// recursively collapses all the sub-views that are stored as properties
Backbone.View.prototype.close = function () {
// calls views closing event handler first, if implemented (optional)
if (this.closing) {
this.closing(); // this for custom cleanup purposes
}
// first loop through childViews[] if defined, in collection views
// populate an array property i.e. this.childViews[] = new ControlViews()
if (this.childViews) {
_.each(this.childViews, function (child) {
child.close();
});
}
// close all child views that are referenced by property, in model views
// add a property for reference i.e. this.toolbar = new ToolbarView();
for (var prop in this) {
if (this[prop] instanceof Backbone.View) {
this[prop].close();
}
}
this.unbind();
this.remove();
// available in Backbone 0.9.9 + when using view.listenTo,
// removes model and collection bindings
// this.stopListening(); // its automatically called by remove()
// remove any model bindings to this view
// (pre Backbone 0.9.9 or if using model.on to bind events)
// if (this.model) {
// this.model.off(null, null, this);
// }
// remove and collection bindings to this view
// (pre Backbone 0.9.9 or if using collection.on to bind events)
// if (this.collection) {
// this.collection.off(null, null, this);
// }
}
Run Code Online (Sandbox Code Playgroud)
然后视图声明如下..
views.TeamView = Backbone.View.extend({
initialize: function () {
// instantiate this array to ensure sub-view destruction on close()
this.childViews = [];
this.listenTo(this.collection, "add", this.add);
this.listenTo(this.collection, "reset", this.reset);
// storing sub-view as a property will ensure destruction on close()
this.editView = new views.EditView({ model: this.model.edits });
$('#edit', this.el).html(this.editView.render().el);
},
add: function (member) {
var memberView = new views.MemberView({ model: member });
this.childViews.push(memberView); // add child to array
var item = memberView.render().el;
this.$el.append(item);
},
reset: function () {
// manually purge child views upon reset
_.each(this.childViews, function (child) {
child.close();
});
this.childViews = [];
},
// render is called externally and should handle case where collection
// was already populated, as is the case if it is recycled
render: function () {
this.$el.empty();
_.each(this.collection.models, function (member) {
this.add(member);
}, this);
return this;
}
// fired by a prototype extension
closing: function () {
// handle other unbinding needs, here
}
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
35319 次 |
| 最近记录: |