我的问题是使用Backbone子视图渲染视图的最佳方法。
虽然围绕这个主题有很多博客,但我还没有找到任何可以应用于这个用例的实用想法。
背景故事
在页面加载时,骨干提取并呈现远程模型和远程页面模板。
页面模板由3个字段集组成,每个字段集包含大量只读数据和图像,并带有[编辑]按钮。
+-----------------------+ +-----------------------+
| ID: ViewA | | ID: ViewB |
| | | |
| | | |
| EDIT | | EDIT |
+-----------------------+ +-----------------------+
+-----------------------+
| ID: ViewC |
| |
| |
| EDIT |
+-----------------------+
当用户点击[edit]时,我想创建一个子视图,获取部分(下划线模板),应用现有模型,最后替换fieldset的innerHTML。
这将使字段集中的先前只读内容可由用户编辑和保存。一旦用户保存(或取消),它应该回到服务器,并重新呈现只读视图。
为了论证,让我们说模板托管在/templates/edit/<fieldsetid>.html
以下是现有代码:
模型和收藏
// Model
window.Page = Backbone.Model.extend();
// Collection
window.PageCollection = Backbone.Collection.extend({
model: Page,
url: '/page/view.json'
});
视图
window.PageView = Backbone.View.extend({
initialize:function () {
this.model.bind("reset", this.render, this);
},
events:{
'click fieldset a[role=edit-fieldset]' : 'edit'
},
edit: function(e){
e.preventDefault();
// @TODO Do some subview awesomeness here?
},
render:function (eventName) {
_.each(this.model.models, function (data) {
$(this.el).append(this.template({data: data.attributes}));
}, this);
return this;
}
});
路由器
var AppRouter = Backbone.Router.extend({
routes:{
"page/view":"pageView"
},
pageView:function (action) {
this.page = new PageCollection();
this.pageView = new PageView({model:this.page});
this.page.fetch();
$('#content').html(this.pageView.render().el);
}
});
模板加载器
// Borrowed from:
// http://coenraets.org/blog/2012/01/backbone-js-lessons-learned-and-improved-sample-app/
// Should probably move to RequireJS and AMDs
utils.loadTemplate(['PageView'], function() {
var app = new AppRouter();
Backbone.history.start();
});
所以考虑到这一点,你有什么想法?我是在正确的轨道上吗?我应该看看另一种模式吗?
提前致谢。
答案 0 :(得分:0)
我通常接近这些情况的方式如下(使用上面现有的'loadTemplate',Page和PageCollection架构):
// Model
window.Page = Backbone.Model.extend();
// Collection
window.PageCollection = Backbone.Collection.extend({
model: Page,
url: '/page/view.json'
});
window.PageView = Backbone.View.extend({
template: templates.pageViewTemplate,
render: function() {
var html = this.map(function(model) {
// Important! We don't need to store a reference to the FieldSetViews.
// Simply render them and by passing in the model, we can update the view
// as needed when the model changes.
//
// This is also good to reduce the potential for memory-leaks.
return new FieldSetView({
model: model
}).render();
});
// Do one DOM update.
this.$el.html(html);
return this.$el;
}
});
window.FieldSetView = Backbone.View.extend({
events: {
"click .edit": "_onEdit"
},
template: templates.fieldSetTemplate,
render: function() {
// Replace the top-level div created by backbone with that of your
// template (i.e fieldset). This gets around having to use
// the tagName property which should really be in your template.
this.setElement(this.template.render(this.model.toJSON()));
return this.$el;
},
_onEdit: function(e) {
// Handle edit mode here by passing the model to another view
// or by enhancing this view to handle both edit and view states.
}
});