Backbone.js model.save()在下划线中触发“过多的递归”错误

时间:2013-11-24 12:10:35

标签: backbone.js

我尝试使用骨干从表单中保存我的模型时遇到了问题。在这里,我希望我的观点实际上是一个编辑形式:

    (function() {

    'use strict';

    var YachtEditor = {};
    window.YachtEditor = YachtEditor;

    var template = function(name) {
        return Mustache.compile($('#' + name + 'Template').html());
    };

    YachtEditor.Tank = Backbone.Model.extend({
        defaults : {
            dCapacity : "",
            sType : ""
        }
    });

    YachtEditor.Tanks = Backbone.Collection.extend({
    //      url: "/rest/tanks",
        localStorage: new Store("tanks"),
        model : YachtEditor.Tank
    });

    YachtEditor.TankView = Backbone.View.extend({
        template: template("tank"),
        events: {
            'click .save' : 'save',
            'click .remove' : 'remove'
        },
        initialize: function() {
            console.log("initialize tank View :");
            console.log(this.model.get("id"));
        },
        render: function() {
            this.$el.html(this.template(this));
            return this;
        },
        save: function() {
            console.log('change');

            var self = this;
            var values = {
                    sType:     self.$("#sType").val(),
                    dCapacity: self.$("#dCapacity").val()
                };

            console.log("dCapacity : " + values.dCapacity);
            console.log("sType : " + values.sType);

            this.model.save(values);
        },
        remove: function() {
            this.model.destroy();
        },
        dCapacity : function() {
            return this.model.get("dCapacity");
        },
        sType : function() {
            return this.model.get("sType");
        }
    });

    YachtEditor.TanksView = Backbone.View.extend({
        el: $("div.tankZone"),
        template: template("tanks"),
        events: {
            "click .add" : "addTank",
            "click .clear" : "clear"
        },
        initialize: function() {
            this.tanks = new YachtEditor.Tanks();
//          this.tanks.on('all', this.render, this);
            this.tanks.fetch();
            this.render();
        },
        render: function() {
            this.$el.html(this.template(this));
            this.tanks.each(this.renderTank, this);
            return this;
        },
        renderTank: function(tank) {
            var view = new YachtEditor.TankView({model: tank});
            $(".tanks").append(view.render().el);
            return this;
        },
        addTank: function() {
            this.tanks.create({});
            this.render();
        },
        clear: function() {
            this.tanks.each(function(tank) {
                tank.destroy();
            });
            this.render();
        }
    });
    ...
    })();

这是我用于每个坦克的胡子模板

<script id="tankTemplate" type="text/x-mustache-template">      
    <div class="tankView">
        <h1>Tank</h1>
        <select id="sType" value="{{ sType }}">
            @for(option <- Tank.Type.values().toList) {
                <option>@option.toString</option>
            }
        </select> 
        <input id="dCapacity" type="text" value="{{ dCapacity }}">
        <button class="destroy">x</button>
    </div>
</script>

我的问题是this.model.save()在下划线中触发“过多的递归”。 JS。 (chrome也显示错误。

以下是错误调用堆栈:

_.extend
_.clone
_.extend.toJSON
_.extend.save
_.extend.update
Backbone.sync
_.extend.sync
_.extend.save
YachtEditor.TankView.Backbone.View.extend.save
st.event.dispatch
y.handle

我怀疑保存是为了回忆模糊事件,但是我找不到明确它的方法......也许我没有使用骨干,因为我应该这样做?

2 个答案:

答案 0 :(得分:1)

除了Yurui Ray Zhang(谢谢)指出的一些问题之外,我的问题是我使用的是来自我在这里找到的一个例子的backbone-localstorage.js:git://github.com/ngauthier/intro-到骨架js.git

当我用我在此处找到的存储替换它时,“过多的递归错误”停止显示:https://github.com/jeromegn/Backbone.localStorage

答案 1 :(得分:0)

一些事情。您将坦克模型定义为

app.Tank = ...

但在您的收藏中,您将其引用为:

model : YachtEditor.Tank

并且在您的视图中,您尝试在元素在页面上呈现之前分配元素:

this.input = {}
this.input.sType     = this.$("#sType");
this.input.dCapacity = this.$("#dCapacity");

我不确定你的视图是如何呈现给页面的,有些人,比如我,喜欢使用render()将模板直接渲染到页面:

render: function() {
  this.$el.html(this.template(this));
   //done, you should be able to see the form on the page now.
},
其他一些人会使用别的东西插入el,例如:

//in another view
tankView.render().$el.appendTo('body');

但无论如何,如果要缓存元素,则需要在将它们渲染到页面后执行,而不是在初始化时执行。

//this method is only called after render() is called! 
cacheElements: function() {
    this.input = {}
    this.input.sType     = this.$("#sType");
    this.input.dCapacity = this.$("#dCapacity");
}

我建议,首先尝试解决这个问题,然后尝试在readForm方法中添加一些控制台日志或调试器,以查看是否正确获取了值:

readForm: function() {
    var input = this.input;
    console.log(input.sType.val());
    console.log(input.dCapacity.val());
    this.model.save({
        sType:     input.sType.val(),
        dCapacity: input.dCapacity.val()
    });
},