使用主干.js中的路由管理单页应用程序中的多个视图实例
Managing multiple instances of views in one page apps using Routes in Backbone.js
我正在使用Backbone.js开发单页应用程序。 我想到的一个问题是,由于没有重新加载页面,因此当创建视图实例时,我假设 View 对象将在应用程序的生命周期内保留在内存中。这对我来说似乎不是很有效,因为如果调用另一条路由,可能不再需要特定的视图。但是,如果返回到原始路线,则以后可能需要"显示"特定视图。那么问题来了,如何最好地管理骨干网中关于路由的视图?
在我的应用程序中,许多视图负责显示特定的"页面",因此共享相同的 DOM 元素。 当调用这些"页面"视图之一时,它将替换先前由上一个视图放置的 DOM 元素中的内容。 因此,不再需要前面的视图。
我是否需要以某种方式手动销毁以前的视图(或者这是否由路由器对象以某种方式处理)? 还是在初始化视图后保留视图更好?
以下示例代码显示了如何在应用程序的路由器中创建视图实例。
/**
* 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();
- 路由不会破坏视图
路由为您提供了与 url 更改进行交互的便捷方式。通过方便,我的意思是当前页面的 url 语义和上下文。例如,url #/!/create/
将调用一个方法,该方法应显示用于创建模型的窗体。此处的上下文是用于创建模型的视图。
- 视图应由开发人员管理
在 Backbone.js 中仍然没有一种众所周知的管理视图的方法,但我更喜欢全局变量的方式。这将确保您的视图实例在整个应用程序中可用,并且所有模块都可以访问它们。例如,这样做
window.App.Contacts.ContactView = new App.Contacts.View.ContactView({model:BenContact});
将通过窗口对象使用于显示 Ben 联系信息的视图可供应用程序模块使用。对于使用相同el
的任何视图,您需要做的就是销毁ContactView
并呈现新视图。
- 您有删除它们的方法
取消委托事件和删除方法可帮助您删除它们。在处理路由哈希更改事件的回调方法中。例如,在处理#/!/view/all
的回调方法(查看所有联系人列表的 url)中,您可能会遇到两个视图现在使用相同的el
的情况,因此您应该销毁ContactView
并呈现ListView
因此在回调中执行此操作
App.Contacts.ContactView.undelegateEvents();
App.Contacts.ContactView.remove();
由于 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({ 初始化 : 函数(){ this.childViews = []; }, 渲染: 函数(){ this.childViews.push(new ChildView); }});
-
第三种选择是让子视图订阅事件父视图触发,以便他们可以在父视图发布"关闭"事件。
我还从您的代码中注意到,您实际上是在子视图类中获取模型。 理想情况下,我建议将模型作为参数传递给构造函数,因为这会将视图与数据分离。它更像MVC风格
- 如何通过osascript处理同一应用程序的两个实例
- Angularjs应用程序的多个实例
- 在两台不同的服务器上运行同一node.js应用程序的两个实例
- 使用AsyncStorage实例化持久应用程序状态
- 在单页应用程序上重用谷歌地图API实例
- 适用于 Android 应用程序的 Java 代码中的实例化异常
- 在 Angular.js 中跨应用程序使用相同的对象实例
- 创建 JavaScript 自定义应用程序的新实例
- 使用主干.js中的路由管理单页应用程序中的多个视图实例
- 在应用程序中获取多个 ID 实例
- 如何拥有具有单独LocalStorage的单独Electron应用程序实例
- 对 Ember 应用程序进行反射/自省,以查找特定模型的实例
- Amazon EC2 实例上的负载测试节点.js应用程序
- 如何在视图中呈现部分 js 或访问在应用程序/资产中的 js.erb 文件中的控制器操作中初始化的实例变量/方法
- 区分浏览器选项卡关闭和刷新(以检测应用程序的多个实例)
- 从应用程序类函数访问控制器实例
- 如何将apache2.2配置为负载均衡器来管理运行javascript应用程序的tomcat实例
- Meteor应用程序-如何实现多实例部署的编排/配置
- 登录到其他选项卡上的一个Web浏览器实例中的应用程序
- 如何调用已运行的应用程序实例