KnockoutJS绑定AJAX调用中的对象列表

时间:2016-02-11 15:28:44

标签: javascript json ajax knockout.js

我的Javascript代码中有一个数据对象,描述如下:

    //Data Object that represents products
    function Product(n, p, t, d) {
        this.name = ko.observable(n);
        this.price = ko.observable(p);
        tags = typeof (t) !== 'undefined' ? t : [];
        this.tags = ko.observableArray(tags);
        discount = typeof (d) !== 'undefined' ? d : 0;
        this.discount = ko.observable(discount);
        this.formattedDiscount = ko.computed(function ()
        { return (this.discount() * 100) + "%"; }
                                 ,this);
    }

然后,我有一个AJAX调用来检索JSON格式的数据

 $(document).ready(function () {
         $.ajax({
             type: "POST",
             url: "ShoppingCartExampleExample.aspx/SendData",
             data: "{}",
             contentType: "application/json; charset=utf-8",
             dataType: "json",
             success: function (msg) {
                 alert(msg.d);               
             }
         });
     });

AJAX调用正在运行,我得到了结果:

[
 {"Discount":0,
  "Name":"Chocolate",
  "Price":"7.99"
  "tags": ["Mars","Snickers"]
 },
 {"Discount":0.05,
  "Name":"Beer",
  "Price":"3.99"
 "tags": ["Large","Extra"]
 }
]

如何将从AJAX调用接收的对象列表映射到我的数据对象? 我想将此列表映射到一个可观察数组,并将tags数组映射到一个可观察数组,因为我有一个foreach绑定填充HTML表来呈现产品和标签。

谢谢

2 个答案:

答案 0 :(得分:0)

假设您的success函数msg.d是您的数组。只需循环遍历数组,并为每个项目调用new Product,然后将结果推送到父视图模型所在的可观察数组中。例如,如果你有类似的东西:

var rootViewModel = function() {
    this.products = ko.observableArray();
    //... whatever other properties and functions you have
}

var myViewModel = new rootViewModel();

然后在您的ajax通话的success功能中,您可以执行以下操作:

success: function (msg) {
    msg.d.forEach(function(item) {
        myViewModel.products.push(new Product(item.Name, item.Price, item.tags. item.Discount));
    }             
}

使用mapping插件可以避免一些这样的管道,这个插件非常易于配置,允许您将您的ajax调用中的普通javascript对象映射到您想要的任何视图模型。

答案 1 :(得分:0)

Knockout utility functions现已包含在最新版本中,是我处理事物的首选方式。映射插件有时会过度使用,如果使用不当,可能会使对象比它们需要的更臃肿。

返回对象数组时,请使用实用程序类:

var newProducts = ko.utils.arrayMap(data, function(dataItem) {
    return new Product(...);
});

ko.utils.arrayPushAll(myViewModel.products, newProducts);

非常直接和支持。您甚至可以将arrayMap直接放入arrayPushAll作为第二个参数,并跳过声明newProducts变量。