1

我完全不知道如何为以下问题实施解决方案:

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

我在这里的 js fiddle中添加了一个测试用例

正如您在小提琴中看到的,狗favorite_snacks可以由用户添加,但我一直在努力编写代码以在实例化视图时解析和呈现它,然后将它们成功保存回 mysql 数据库.

我将不胜感激任何帮助,我整个周末都在用头撞我的桌子试图弄清楚。

4

1 回答 1

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();

检查工作小提琴

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

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

于 2013-05-13T21:33:05.423 回答