我正在使用Backbone.js开发单页应用。我遇到的一个问题是,由于一个人没有重新加载页面,当一个人创建一个View实例时,我认为,View对象将在应用程序的生命周期内保留在内存中。这对我来说似乎不是很有效,因为如果调用另一个路由,则可能不再需要特定视图。但是,如果返回到原始路线,则稍后可能需要“显示”特定视图。所以问题是,如何最好地管理Backbone中关于路由的视图?
在我的应用程序中,许多视图负责显示特定的“页面”,因此共享相同的DOM元素。当调用其中一个“页面”视图时,它将替换先前视图中先前放置的DOM元素中的内容。因此不再需要先前的视图。
我是否需要以某种方式手动销毁前一个View(或者这是由Router对象以某种方式处理)?或者,一旦初始化后留下观点会更好吗?
以下示例代码显示了如何在应用程序的路由器中创建视图实例。
/**
* View - List of contacts
*/
var ListContactsView = Backbone.View.extend({
el: '#content',
template: _.template($('#list-contacts-tpl').html()),
initialize: function() {
_.bindAll(this, 'render');
this.collection = new Contacts();
this.collection.bind('reset', this.render);
this.collection.fetch();
},
render: function() {
this.$el.hide();
this.$el.html(this.template({ contacts: this.collection }));
this.$el.fadeIn(500);
}
});
/**
* View - Display single contact
*/
var DisplayContactView = Backbone.View.extend({
el: '#content',
events: {
'click #delete-contact-button': 'deleteContact'
},
template: _.template($('#display-contact-tpl').html()),
initialize: function() {
_.bindAll(this, 'deleteContact', 'render');
// Create reference to event aggregator object.
if (typeof this.options.id === 'undefined') {
throw new Error('View DisplayContactView initialized without _id parameter.');
}
this.model = new Contact({ _id: this.options.id });
// Add parse method since parsing is not done by collection in this
// instance, as this model is not called in the scope of collection
// Contacts.
this.model.parse = function(response) {
return response.data;
};
this.model.bind('change', this.render);
this.model.fetch();
},
deleteContact: function(id) {
// Trigger deleteContact event.
this.eventAggregator.trigger('deleteContact', id);
},
render: function() {
this.$el.html(this.template({ contact: this.model.attributes }));
}
});
/**
* Page routes
*/
var $content = $('#content');
var ClientSideRouter = Backbone.Router.extend({
routes: {
'browse': 'browse',
'browse/view/:id': 'browseViewContact',
'orgs': 'orgs',
'orgs/:orgName': 'orgs',
'orgs/:orgName/:id': 'orgs',
'contact/add': 'addContact',
'contact/view/:id': 'viewContact',
'contact/delete/:id': 'confirmDelete',
'*path': 'defaultPage'
},
addContact: function() {
// Display contact edit form.
var editContactFormView = new EditContactFormView();
// Display email field in edit form.
},
browse: function() {
var listContactsView = new ListContactsView();
},
browseViewContact: function(id) {
var displayContactView = new DisplayContactView({ id: id });
},
defaultPage: function(path) {
$content.html('Default');
},
home: function() {
$content.html('Home');
},
viewContact: function(id) {
$.ajax({
url: '/contact/view/' + id,
dataType: 'html',
success: function(data) {
$content.html(data);
}
});
}
});
var clientSideRouter = new ClientSideRouter();
Backbone.history.start();
答案 0 :(得分:2)
路由为您提供了与网址更改进行交互的便捷方式。方便我指的是url语义和当前页面的上下文。例如,url #/!/create/
将调用应显示表单以创建模型的方法。这里的上下文是创建模型的视图。
在Backbone.js中管理视图仍然不存在众所周知的方式,但我更喜欢全局变量的方式。这将确保您的视图实例在整个应用程序中可用,并且所有模块都可以访问它们。例如,这样做
window.App.Contacts.ContactView = new App.Contacts.View.ContactView({model:BenContact});
将使视图用于通过窗口对象显示Ben的应用程序模块可用的联系信息。对于使用相同el
的任何视图,您只需要销毁ContactView
并呈现新视图。
Undelegate事件和Remove方法可帮助您删除它们。处理路由散列更改事件的回调方法内部。例如,在处理#/!/view/all
的回调方法(用于查看所有联系人列表的网址)中,您可能会遇到两个视图现在使用相同el
的情况,因此您应该销毁ContactView
并渲染ListView
以便在回调中执行此操作
App.Contacts.ContactView.undelegateEvents();
App.Contacts.ContactView.remove();
答案 1 :(得分:1)
由于Backbone.js没有内置的视图合成支持,因此在跟踪子视图时可以遵循几种模式。
Derick Bailey演示了扩展Backbone.View以允许视图 自己清理干净 - http://lostechies.com/derickbailey/2011/09/15/zombies-run-managing-page-transitions-in-backbone-apps/
另一种方法是将子视图添加到该属性 父视图状态并在父视图状态为时手动清除它们 除去。
var ParentView = Backbone.View.extend({ initialize:function(){ this.childViews = []; }, render:function(){ this.childViews.push(new ChildView); } });
第三种方法是让子视图订阅事件 父视图触发,以便他们可以清理时 父视图发布“关闭”事件。
此外,我从您的代码中注意到您实际上是在您的子视图类中获取模型。理想情况下,我建议将模型作为参数传递给构造函数,因为这会将视图与数据分离。它更像MVC-ish