2013-05-13 77 views
1

我完全失去了如何实现以下问题的解决方案:如何呈现和保存骨干模型的动态属性?

我有一个骨干视图,填充了来自骨干模型的属性。在此视图中,显示属性,对于其中一个属性,用户需要能够添加或修改现有属性。这最适合作为骨干模型中的一组属性(我认为)。

我加入的js fiddle here

测试用例正如你可以在小提琴看到,狗的favorite_snacks可以由用户加入,但我对如何编写代码来解析被完全挣扎并在实例化视图时将其渲染,然后成功将它们保存回mysql数据库。

我非常感谢这方面的帮助,整个周末我一直在头撞我的桌子,试图弄清楚它。

回答

0

确保视图和模型独立并完全分离,以便您的代码可以在以后管理,总是一个更好的主意。

所以在这种情况下,每个宠物可以有一个或许多最喜欢的零食。因此,基本上你期望小吃在这里,而不是单一小吃模型。

因此,最好创建一个单独的小吃集合,然后Snack Model。然后保持一个独立的视图SnackListItem,然后遍历的SnackCollection列表和渲染视图每个项目..

所以对他们俩的

<div id="foo"></div> 
<script type="text/template" id="pet-view-template"> 
    <p> <span><b> Dog Name: </b> </span> <%= name %> </p> 
     <p> <span><b> Dog Color: </b></span> <%= color %> </p> 
    <h4> favorite snacks </h4> 
    <ul class="snacks-list"> 
    </ul> 
    snack name: <input type="text" class="snack-name" /> 
    cost : <input type="text" class="snack-cost" />  
    <button class="add-snack">add snack</button > 
</script> 

<script type="text/template" id="snack-view-template"> 
    <b>snack name:</b> <span> <%=favorite_snacks %> </span> :: 
    <b>cost: </b><span> <%= favorite_snack_cost %> </span> 

     <b class="toggle-change"> Change </b> 
     <span class="modify-fields hide"> 
      <b class="modify">snack name:</b> <input type="text" class="modify-name" data-key="favorite_snacks" /> 
      <b class="modify">snack cost:</b> <input type="text" class="modify-cost" data-key="favorite_snack_cost" />  
     </span> 
</script> 

我创建了一个独立的视图,并创建独立的模板小吃集合的模型。 这仍然可以优化。

的Javascript

// Create a Dog Model 
var Dog = Backbone.Model.extend({ 
    defaults: { 
     name: 'New dog', 
     color: 'color' 
    } 
}); 

// Create a collection of dogs 
var Dogs = Backbone.Collection.extend({ 
    model: Dog 
}); 

// Create a model for Snacks 
var Snack = Backbone.Model.extend({ 
    defaults: { 
     favorite_snacks: 'bacon', 
     favorite_snack_cost: '52' 
    } 
}); 

// Create a collection of Snacks 
var Snacks = Backbone.Collection.extend({ 
    model: Snack 
}); 

// Define the model for a Dog 
var dog = new Dog({ 
    name: "Spot", 
    color: "white" 
}); 

// Create a View for the Snack Item 
var SnackItemView = Backbone.View.extend({ 
    tagName : 'li', 
    className: 'snacks', 
    template: _.template($('#snack-view-template').html()), 
    initialize: function() { 
     // Need to bind to save the context of this to the view 
     _.bind('toggleChange', this); 
     // Need to listen to the Model change event and render the view again 
     // as the new data has to be reflected 
     this.listenTo(this.model, 'change' , this.render); 
    },  
    // Assign events for the fields inside Snacks view 
    events : { 
     'click .toggle-change' : 'toggleChange', 
     'change input'   : 'modifyData' 
    }, 
    toggleChange: function() { 
     var $change = $('.modify-fields', this.$el); 
     $change.hasClass('hide') ? $change.removeClass('hide') : $change.addClass('hide'); 
    }, 
    // This will captue the data from the inputs and trigger the change event on the model 
    modifyData: function(e) { 
     var value = $(e.currentTarget).val(), 
      key = $(e.currentTarget).data('key'); 
     this.model.set(key,value); 
    }, 
    render: function() { 
     this.$el.html(this.template(this.model.toJSON())); 
     return this; 
    } 
}); 

var PetView = Backbone.View.extend({ 
    el: '#foo', 
    template: _.template($('#pet-view-template').html()), 
    initialize: function() { 
     this.collection = (this.collection && this.collection instanceof Backbone.Collection) || new Snacks(Snack); 
    }, 
    events: { 
     'click .add-snack' : 'addSnack' 
    }, 
    addSnack: function() { 
     // Render new snack Item 
     var newSnack = new Snack({ 
      favorite_snacks: $('.snack-name', this.$el).val(), 
      favorite_snack_cost: $('.snack-cost', this.$el).val() 
     }); 
     this.renderSnackView(newSnack); 
     // Clear the inputs 
     $('input', this.$el).val(''); 
    }, 
    // render each snack view 
    renderSnackView: function (snack) { 
     var snackView = new SnackItemView({ 
      model: snack 
     }); 
     $('.snacks-list', this.$el).append(snackView.el); 
     snackView.render(); 
    }, 
    render: function() { 
     var thisView = this; 
     // Append the PetView 
     this.$el.html(this.template(this.model.toJSON())); 
     // Iterate over each snack collection of the pet and render that item 
     _.each(this.collection.models, function (snack) { 
      thisView.renderSnackView(snack); 
     }); 
     return this; 
    } 
}); 



var petView = new PetView({ 
    model: dog 
}); 
petView.render(); 

Check the working fiddle

我已经用注释来解释一些代码。最初学习骨干网很困难,因为我刚刚开始使用它,我知道我经历的麻烦。但一旦你习惯了它,它是非常简单但功能强大..希望这会有所帮助:)

但是,当您尝试构建应用程序时,您需要销毁未使用的视图和事件以减少内存泄漏。