【问题标题】:Knockout.js and nullsKnockout.js 和空值
【发布时间】:2012-06-14 23:40:56
【问题描述】:

我在一个使用 JSON 的富 Web 客户端中结合使用 Knockout.js + Knockout 映射插件 + jQuery一个 RESTful API。

我需要一些关于在我的视图模型中如何处理空值的指导。这是我的场景和我遇到的问题:

REST API 返回的大多数数据成员都是可为空的。为了解决这个问题,我向映射插件传递了一个带有空值的 JSON 样本:

um.jsonMaps.campaign = {
    "priority": null,
    "recipientListId": null,
    "autoPrepare": null,
    "timeToSend": null
}

我像这样进行初始绑定:

this.model = ko.mapping.fromJS(um.jsonMaps.campaign);

以下是来自 API 调用的一些数据:

var data= {
    "priority": 95,
    "recipientListId": "a2aac72a-59f6-45da-a636-a48cc2b20137",
    "autoPrepare": false,
    "timeToSend": null
}

...绑定如下:

ko.mapping.fromJS(data, this.viewModel.model);

问题是,如果用户修改或触摸任何绑定到此数据的 UI 元素,他们会隐式地将模型中的数据成员转换为 带引号的字符串文字 .因此,如果用户添加一些文本并将其删除,整数 95 将变为 "95"。如果在 UI 中触摸了 API 中为 null 的值,它就会变为 ""(例如空字符串)。

我需要整数和空值在编辑后保留为整数和空值。

【问题讨论】:

  • 如果您想继续使用映射插件并且不想提供广泛的映射选项,那么您可以查看使用包装值绑定的自定义绑定,如此答案中所述:@987654321 @.
  • 这是另一个很好的链接。立即查看信息。
  • 我查看了此信息,但觉得自定义绑定引入了我并不真正需要的复杂程度。我最终接受的答案起到了作用,同时让我继续使用本机“文本”和“值”绑定。对于自定义绑定和 KO.computed observables,我不得不编写大量代码,因为我们的 API 需要对空值(字符串、数字、日期甚至布尔值)进行特殊处理。使用计算的 observables 实际上减少了我的代码。

标签: jquery rest null knockout.js knockout-mapping-plugin


【解决方案1】:

在我的项目中,我最终通过来自服务器的数据创建了视图模型。我添加了带有 getter 和 setter 的新属性,以便在需要时写入数值:

function DataViewModel(dataModel) {
    var self = this;
    self.priority = ko.observable(dataModel.priority);
    self.recipientListId = ko.observable(dataModel.recipientListId);
    self.autoPrepare = ko.observable(dataModel.autoPrepare);
    self.timeToSend = ko.observable(dataModel.timeToSend);



    self.priorityKo = ko.computed({
        read: function () {
            return self.priority().toFixed(2);
        },
        write: function (value) {
            value = parseFloat(value.replace(/[^\.\d]/g, ""));
            if (isNaN(value)) {
                self.priority(-1); // to fire 'changed' event
                self.priority(0); // final value in case of incorrect user input
            } else {
                self.priority(value); // real numeric value
            }
        },
        owner: this
    });

您的映射将如下所示:

this.model = ko.mapping.fromJS(new DataViewModel(um.jsonMaps.campaign));

【讨论】:

  • 好的,这看起来可以解决问题。这意味着我将不得不放弃使用映射插件,但我喜欢微调不同计算数据成员的能力。对于被转换为空字符串的空值(当我调用我们的更新 API 时,这就是目前正在杀死我的东西),我将把这些值转换回空值。
  • 我会在明天验证这是否适合我,如果可以,我会接受这个答案。谢谢!
  • 没问题,在我的项目中,我还实现了一种从视图模型创建服务器对象(将其发送到服务器)的方法,但我认为这可以使用映射插件存档
  • 对。我的意思是我必须放弃使用映射插件作为一种“黑匣子”,它只是在没有任何其他干预的情况下发挥它的魔力——这是插件最好的部分。理想情况下,当我传入初始 dataModel 以及我希望它继续使用的数据类型时,插件将支持这一点:string、bool、int、float 或 null。
  • 我已经接受了这个作为答案。我也查看了自定义绑定选项,但对于我的用例,这个实现更简洁。我最终做了一些小的修改(这些修改很难在这个 UI 中进行交流[我对 S.O. 模型的一个小挫折之一是接受答案但无法显示使其适用于我的场景所需的代码更改)。在我的版本中,我这样做: self.priority_KO = ko.observable(dataModel.priority) 然后: self.priority = ko.computed(...) 这意味着我可以在我的标记中绑定到“优先级”。跨度>
【解决方案2】:

您可以使用 Ryan 的 Smart Dirty Flag 扩展作为如何处理它的基础。

或者您可以手动完成同样的事情,但他的文章仍然是您正在处理的问题的一个很好的起点。

【讨论】:

  • 感谢您的链接。我会看看。我在其他地方看到过对这篇文章的引用。猜猜是时候打印出来了,终于读完了!
猜你喜欢
  • 2017-09-13
  • 2011-05-07
  • 2015-05-22
  • 2014-07-24
  • 1970-01-01
  • 2011-11-15
  • 1970-01-01
  • 2023-03-03
  • 2013-12-20
相关资源
最近更新 更多