我在backbone.js中为联系人管理器实现了视图/编辑视图。 Web建议使用名为ContactView和ContactEdit的子视图创建一个Contact类。问题是,这些需要占用DOM中的相同元素,因此我无法将子元素嵌套在父元素中。这是因为从外部来看,我希望父视图只能引用联系人,就好像这些孩子是私人的一样。我试过这个,它第一次渲染():
initialize: function() {
this.view[0] = new CL.Views.ContactView({model: this.model, el: this.el});
this.view[1] = new CL.Views.ContactEdit({model: this.model, el: this.el});
},
render: function() {
this.view[0].render();
return this;
}
但是我无法交换意见。我尝试了这个.view [0] .remove()以及我能想到的一切,但是不能让浏览和编辑视图使用相同的el互相交换。
我认为这意味着在一个视图中有两个模板并且只是交换它们会更好,这些模板已经基本上可以工作了。我认为它的主干.js不能很好地处理DOM中同一级别的视图的继承。
我更倾向于避免使用backbone.js扩展,但是要遵循它们实现的任何模式。我试图这样做"对"因为查看/编辑是我们应用程序中表单的常见模式。
P.S。说明这个问题的另一种方法是,如果没有包含它们的父视图,如何隐藏视图并将其替换为backbone.js中的另一个视图?
提前感谢您提供的任何帮助。
答案 0 :(得分:1)
我不太明白,如果您希望获得Collection
Models
的视图,或者您想要查看处理单个Model
的视图吗?
然后你可以坚持一个观点。只是让一些事件听取您的操作启用或禁用编辑功能。 (即使在dom元素上设置contenteditable =“true”,也可以这样做)
我强烈建议您使用backbone.marionette或chaplinjs等工具。他们会为你节省大量时间。
以下示例适用于Backbone.Marionette
示例模板
<script type="text/template" id="contact-view-template">
<span data-bind="firstName"></span>
<span data-bind="lastName"></span>
<span data-bind="email"></span>
<a href="#" data-action="edit">
<a href="#" data-action="save" style="display:none">
</script>
观看代码:
ContactView = Marionette.ItemView.extend({
template:"#contact-view-template",
events:{
"click [data-action=edit]":"edit",
"click [data-action=save]":"save"
},
edit:function(){
this.$("[data-action=edit]").hide();
this.$("[data-action=save]").show();
this.$("[data-bind]").attr("contenteditable",true);
},
save:function(){
var value = {};
_.each(this.$("[data-bind]",function(el){
value[el.dataset['bind']]= $(el).val() || $(el).text();
}));
this.model.set(value);
// add your validation here
this.model.save();
}
});
ContactListEditView = Marionette.CompositeView.extend({
itemView:ContactView.extend({
tagName:"li"
}),
itemViewContainer:"ul",
template:_.template("<h1>ContactList</h1><p>feel free to edit</p><ul></ul>")
});
(我希望我没有犯过任何严重的错误):
ContactEditView = Marionette.ItemView.extend({
template:"#contact-edit-view", // your template & bindings
events:{
"click [data-action=save]":"save"
},
save:function(){
var value = {};
_.each(this.$("[data-bind]",function(el){
value[el.dataset['bind']]= $(el).val() || $(el).text();
}));
this.model.set(value);
this.model.save();
}
});
ContactListView = Marionette.CompositeView.extend({
itemView:Marionette.ItemView.extend({
template:"#contact-view-template",
events:{
"click [data-action=edit]":"edit"
},
edit:function(){
this.trigger("edit",this);
}
}),
regions:{
"edit":"[data-region=edit]"
},
initialize:function(){
this.on("itemview:edit",function(view){
this.edit.show(new ContactEditView({model:view.model}));
}.bind(this));
}
});
答案 1 :(得分:0)
我认为您的问题源于您的父视图与子视图共享相同的元素。当您呈现ContactView
或ContactEdit
视图时,它会替换DOM元素,当您remove
子视图时,它(根据定义)也会删除父视图元素,因为它们是相同的元素。
相反,您应该组合父视图,以便将子视图呈现为到容器元素中。像
这样的东西<!-- .contact-container is the parent view el -->
<section class="contact-container">
</section>
然后将子视图渲染到容器中:
initialize: function() {
//don't give the views an element, let them render into the detached
//element generated by Backbone
this.view[0] = new CL.Views.ContactView({model: this.model});
this.view[1] = new CL.Views.ContactEdit({model: this.model});
this.currentViewIndex = 0;
},
render: function() {
//replace the contents with the new view
this.view[this.currentViewIndex].render();
this.$el.html(this.view.el);
return this;
},
swap: function() {
var i = this.currentViewIndex;
this.view[i].remove();
//toggle current view between 0 and 1
this.currentViewIndex = i === 0 ? 1: 0;
this.render();
}
然后你得到
<!-- .contact-container is the parent view el -->
<section class="contact-container">
<div><!-- your child element --></div>
</section>
答案 2 :(得分:0)
如果我正确理解您的问题,您需要一个从基础View
继承的视图,以便他们可以使用相同的Model
自由操作。
/** Declare base View with specific Model. */
var baseView = Backbone.View.extend({
model: someModel
});
var contactView = baseView.extend({
initialize: function() {
/** Do work specific to contact view. */
}
});
var editContactView = baseView.extend({
initialize: function() {
/** Do work specific to contact edit. */
}
});
var mainView = Backbone.View.extend({
initialize: function() {
/** Initialize two contact views */
new contactView({ });
new editContactView({ });
}
});