Backbone.js:"超出最大调用堆栈大小"错误

时间:2012-06-18 02:29:09

标签: backbone.js document mousemove

假设我有一个模型和一个视图,这个视图有两个方法:一个是绑定文件mousemove事件而另一个是unbind方法,defalut我给文档mousemove事件,一旦模型的enable值改变了我将调用视图的unbind方法:

    window.ConfigModel = Backbone.Model.extend({
        defaults: {
            'enable':0
        },
        initialize: function(){
            this.bind("change:enable", function () {
                var portView2 = new PortView();
                portView2.viewOff();                        
            });
        },
        change:function () {
            this.set('enable', 9);
        }
     })

    window.PortView = Backbone.View.extend({
        viewOn: function () {
            $(document).on('mousemove', function () {
                console.log('move')
            })
        },
        viewOff: function () {
            $(document).off('mousemove');
        }
    })

然后我在文档上放了input来调用模型更改:

    $('input').click(function () {
        var configModel = new ConfigModel();
        configModel.change();
    })

启动脚本是:

var portView1 = new PortView();
portView1.viewOn();

问题是,一旦我调用点击输入按钮,chrome就会告诉我一个错误:Maximum call stack size exceeded似乎change多次调用。所以我的问题是什么问题,如何我可以解决这个问题

1 个答案:

答案 0 :(得分:1)

Backbone模型已经有change method

  

更改 model.change()

     

为每个已更改的属性手动触发"change"事件和"change:attribute"事件。如果您已将{silent: true}传递给设置功能以便快速更改模型,那么当您全部完成时,您需要致电model.change()

据说Backbone内部的某些内容正试图调用configModel.change()并获取change的版本,这会触发Backbone中的另一个change()调用,该调用将运行您的change ...直到堆栈爆炸。

您应该为change方法使用其他名称。


那就是说,你的代码结构有些奇怪。听取事件本身的模型很好,但创建视图的模型很奇怪:

initialize: function() {
    this.bind("change:enable", function () {
        var portView2 = new PortView();
        portView2.viewOff();                        
    });
}

实例化一个视图只是为了调用单个方法然后将其抛弃是很奇怪,因为创建一个新模型只是为了触发一个事件。

我认为您可能希望将单个ConfigModel实例作为应用程序状态的一部分,例如app.config。然后你的click处理程序会与该模型对话:

$('input').click(function () {
    app.config.enable_level_9(); // or whatever your 'change' gets renamed to
});

然后你会有一些应用程序的其他部分(不一定是视图),它会监听app.config的更改并采取相应的行动:

app.viewOn = function() {
    $(document).on('mousemove', function() {
        console.log('move')
    });
};
app.viewOff = function() {
    $(document).off('mousemove');
};
app.init = function() {
    app.config = new ConfigModel();
    app.viewOn();
    $('input').click(function () {
        app.config.enable_level_9();
    });
    // ...
};

然后通过一次app.init()调用启动应用程序:

$(function() {
    app.init();
});