【问题标题】:Backbone.js: avoid view→model→view double conversionBackbone.js:避免视图→模型→视图双重转换
【发布时间】:2013-04-05 02:25:01
【问题描述】:

我正在尝试构建this:

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

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

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

我怎样才能避免这种情况?


更新:

我想知道在 MVC 框架(例如 Backbone.js)中处理双向绑定的优雅方式。

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。

【问题讨论】:

  • 我通常乘以生成非小数整数所需的任何因子 10,进行数学运算,然后在完成后除以因子 10,以避免 javascript 十进制数学的粗俗。

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


【解决方案1】:

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

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

正如 Backbone 文档所说:

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

【讨论】:

    【解决方案2】:

    想到了两种方法。正如 Kinakuta 提到的,您可以执行以下操作,这样您就可以对整数而不是小数进行数学运算:

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

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

    更新:使用简单的临时转换器,Backbone 需要 3.5 倍的代码也就不足为奇了。 MVC 框架可以减少大型项目中的臃肿,但对于小型应用程序而言,这可能是矫枉过正。例如想象一下使用 Backbone 显示“Hello World”。

    至于你的问题,当一个改变时只渲染 other 输入值,而不是两者?如果 F 输入发生变化,则重新渲染 C 框中的值。对于ModelBinder,我将通过在我的模型中包含两个属性来做到这一点:tempFtempC。当一个被修改时,我重新计算另一个,ModelBinder 会自动显示它。或者您可以不使用 MB,只听更改事件。

    【讨论】:

    • 舍入只是一个技巧。我想知道如何避免不必要的重新渲染。请详细说明。
    • @NVI 查看我的更新。您的主要问题是您不应该重新渲染用户更改的输入字段,只需重新渲染另一个。
    【解决方案3】:

    在您保存开始转换的输入字段的视图级别设置一个变量,这样您就不会在该字段上调用转换函数。

    【讨论】:

      猜你喜欢
      • 2012-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多