如何渲染和保存Backbone模型的动态属性?

时间:2013-05-13 19:29:59

标签: javascript jquery backbone.js

我完全迷失了如何为以下问题实施解决方案:

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

我在js fiddle here

中添加了一个测试用例

正如你可以在小提琴中看到的那样,狗的favorite_snacks可以由用户添加,但我一直在努力研究如何编写代码来解析并在实例化视图时渲染它然后将它们成功保存回mysql数据库。

我非常感谢任何有关这方面的帮助,我整个周末一直在试着弄清楚我的脑袋。

1 个答案:

答案 0 :(得分:0)

始终更好的做法是确保视图和模型独立完成并完全解耦,以便以后管理您的代码。

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

因此最好创建一个单独的Snacks Collection然后再创建一个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>

我为Snacks集合创建了一个单独的视图和模型。 这仍然可以优化。

<强>的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

我用评论来解释一些代码。最初学习骨干很难,因为我刚刚开始使用它,我知道我经历过的麻烦。但是一旦你习惯它,它就会非常简单而又强大。希望这有助于:)

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