Backbone.js:避免查看→模型→查看双重转换

时间:2013-04-05 02:25:01

标签: model-view-controller data-binding backbone.js model-binding

我正在尝试构建this:
enter image description here

当我在左侧编辑字段时,它应该更新右侧的字段,反之亦然。

  • 在输入字段中编辑值会导致文本光标在其末尾跳转。

  • 在华氏度字段中键入“2”会被替换为1.999999999999,如屏幕截图所示。这是因为双重转换:
    查看Fº→模型的Cº→查看Fº。

recoil

我该如何避免?


更新

我想知道在Backbone.js等MVC框架中处理双向绑定的优雅方法。

MVC

var Temperature = Backbone.Model.extend({
    defaults: {
        celsius: 0
    },
    fahrenheit: function(value) {
        if (typeof value == 'undefined') {
            return this.c2f(this.get('celsius'));
        }
        value = parseFloat(value);
        this.set('celsius', this.f2c(value));
    },
    c2f: function(c) {
        return 9/5 * c + 32;
    },
    f2c: function(f) {
        return 5/9 * (f - 32);
    }
});


var TemperatureView = Backbone.View.extend({
    el: document.body,
    model: new Temperature(),
    events: {
        "input #celsius": "updateCelsius",
        "input #fahrenheit": "updateFahrenheit"
    },
    initialize: function() {
        this.listenTo(this.model, 'change:celsius', this.render);
        this.render();
    },
    render: function() {
        this.$('#celsius').val(this.model.get('celsius'));
        this.$('#fahrenheit').val(this.model.fahrenheit());
    },
    updateCelsius: function(event) {
        this.model.set('celsius', event.target.value);
    },
    updateFahrenheit: function(event) {
        this.model.fahrenheit(event.target.value);
    }
});

var temperatureView = new TemperatureView();

没有MVC

celsius.oninput = function(e) {
    fahrenheit.value = c2f(e.target.value)
}
fahrenheit.oninput = function(e) {
    celsius.value = f2c(e.target.value)
}
function c2f(c) {
    return 9/5 * parseFloat(c) + 32;
}
function f2c(f) {
    return 5/9 * (f - 32);
}

它不仅可以解决问题,还可以减少代码3.5⨉。显然我做的MVC错了。

3 个答案:

答案 0 :(得分:5)

这是我对此的看法;而是在交互式视图中呈现每个更改的整个视图,使用视图的jQuery或普通JS上下文,就像非MVC示例一样。

http://jsbin.com/fomugixe/1/edit

正如Backbone文档所说:

  

避免“双向数据绑定”。虽然它确实是一个漂亮的演示,并且适用于最基本的CRUD,但它在您的真实应用程序中并不是非常有用。有时您希望更新每个按键,有时是模糊,有时是在面板关闭时,有时是在点击“保存”按钮时。

答案 1 :(得分:1)

我想到了两种方法。正如Kinakuta所提到的,你可以做类似下面的事情,所以你的数学是整数而不是小数:

temp = ((oldTemp * 100) * conversion stuff) / 100

根据您希望应用程序的复杂程度,您还可以使用Backbone.ModelBinder之类的内容。它会自动将您的视图绑定到您的模型,因此当一个更新时,另一个会自动更新。然后,您可以将转换器功能附加到绑定,这样当您的值变为view -> modelmodel -> view时,它将通过转换器运行。如果这个想法让你感兴趣,我可以详细说明。

更新:使用简单的临时转换器,Backbone需要3.5倍的代码并不奇怪。 MVC框架可以减少大型项目中的膨胀,但对于小型应用程序,它可能是过度的。例如想象一下使用Backbone来显示“Hello World”。

至于你的问题,如果只更改一个其他输入值,而不是两者都是如何?如果F输入改变,则在C框中重新渲染值。使用ModelBinder我会在模型中包含两个属性:tempFtempC。当一个被修改时,我重新计算另一个,ModelBinder自动显示它。或者你可以不用MB而只是听取改变事件。

答案 2 :(得分:0)

在视图级别设置一个变量,其中包含开始转换的输入字段,因此您不会在该字段上调用转换函数。