将从服务器接收到的对象转换为具有 ko 可观察属性的对象

Convert object received from server into object with ko observable properties

我对看似简单的想法有疑问。

我正在尝试根据服务器提供的数据动态创建 ko.observable()

服务器正在向我发送一个 ~240 值 JSON 数组。我想为每个对象创建一个可观察对象,因为我将它们放入在线表格中。

第一次尝试

function AppViewModel() {

  var self = this;

  var data = {};

  $.getJSON("/record/20001", function(data) {
    $.each(data, function(i, val) {
      self.data[i] = ko.observable(val);
    });
  });


  self.test = 5;

  self.test2 = ko.observable(69);


}

vm = new AppViewModel();
ko.applyBindings(vm);

因此我无法访问任何数据。

第二次尝试成功了

function AppViewModel() {

    var self = this;
    self.abnorm_comment = ko.observable();
    self.abnorm_test1 = ko.observable();
    self.abo_sys_spec = ko.observable();
    self.access_location = ko.observable();
    self.ace_inhibit = ko.observable();

    /* 
    A myriad of line like these, written by hand
    */

    self.xray_other = ko.observable();


    $.getJSON("/record/20001", function (data) {
        $.each(data, function (i, val) {
            self[i](val);
        });
    });

    self.test = 5;

    self.test2 = ko.observable(69);


}

我想做什么

function AppViewModel() {

    var self = this;

    var data = {};


    $.getJSON("/record/20001", function (data) {
        $.each(data, function (i, val) {
            self.data[i] = ko.observable(val);
        });
    });

}

然后像这样访问它:

<input type="text" data-bind="value: data.case_id">

第一次尝试时,我的视图模型中没有数据。如果我在 Chrome 控制台中调出 vm 变量,它确实有数据。

我是不是做错了什么?对于这么多可观察对象,第二种方法看起来不太好。

如果我遗漏了一些明显的东西,请告诉我

个人解决方案

最后我在应用绑定和 AJAX 服务器请求之间遇到了竞争条件。我也最终使用了@JotaBe推荐的插件

这在过去对我来说很可靠:

jsonToObservable = function (obj, data) {

    for (var p in data) {
        var temp = data[p];

        obj[p] = ko.observable(temp);

    }
};

您可以使用 ko.mapping 插件,它将为您完成。

优点是这个插件经过了很好的测试,能够映射更复杂的数据,如数组或嵌套属性。

您可以从 JSON 或已实例化的 JavaScript 对象映射。语法就这么简单:

var viewModel = ko.mapping.fromJSON(data);

另一个优点是它还可以根据来自服务器的新更新数据更新您的本地映射副本,而无需重建整个对象。这也有助于更新视图,而无需重建(或取消绑定)它。

最后一个优势是它还允许取回 JSON 或 JavaScript 对象,如果您需要 post 将其返回到服务器,就像这样:

var unmapped = ko.mapping.toJS(viewModel);