交换/切换/交换backbone.js视图到位?

时间:2013-01-25 01:10:43

标签: backbone.js view switch-statement exchange-server swap

我在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中的另一个视图?

提前感谢您提供的任何帮助。

3 个答案:

答案 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>")
});

如果您需要1个编辑视图和多个不可编辑的视图

(我希望我没有犯过任何严重的错误):

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)

我认为您的问题源于您的父视图与子视图共享相同的元素。当您呈现ContactViewContactEdit视图时,它会替换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({ });
   }
});