1

服务器向客户端发送一个复杂对象的位置,目标是从 C# 的“foreach”转换到 KnockoutJS 的“data-bind="foreach:”,请考虑使用各种信息填充购物车的这段代码:

@{
    foreach (var item in GetItems(Model))
    {
    <dt>
        <input type="radio" id='mode_@(item.ID)' name="mode" value="@item.ID" />
        @item.Label - $@item.PriceToAdd
    </dt>
    <dd>
        @Html.Raw(item.Explanation) </dd>
        }
    }
}

是否应该在渲染视图之前调整服务器的代码以展平对象,或者 KnockoutJS 是否可以处理展开它?如果服务器发送 JSON 会更容易吗?

跟进: 很明显,问题归结为映射插件,mfanto 的第一个答案让我成功了:

self.items = ko.mapping.fromJS(@Html.Raw(JsonConvert.SerializeObject(Model.Items)));

firebug 向我显示以下输出:

self.items = ko.mapping.fromJS([{"ID":60},{"ID":62},{"ID":63},{"ID":64},{"ID":9}]);

也许映射器失败是因为我的一个项目(id = 9)与其他项目具有不同的元素。

可能我需要研究映射器的一种更先进的用法?

格式化输出比较 JsonConvert 与 JavaScriptSerializer 返回的值

...
self.itemsJSON = ko.mapping.fromJS(@Html.Raw(JsonConvert.SerializeObject(Model.Items)));
self.items = @Html.Raw(new JavaScriptSerializer().Serialize(Model.Items));

当上面的代码渲染到 Firebug 中的断点时:

self.itemsJSON = ko.mapping.fromJS([{"ID":60},{"ID":62},{"ID":63},{"ID":64},{"ID":9}]);
self.items = [  //line breaks inserted for clarity
{"Explanation":"Item1's text.","Label":"Item1's Label","MsgConfirm":null,"PriceToAdd":1255,"TaxExempt":false,"PercentToAdd":0,"SortOrder":1,"ID":60},
{"Explanation":"Item2's text.","Label":"Item2's Label","MsgConfirm":null,"PriceToAdd":1255,"TaxExempt":false,"PercentToAdd":0,"SortOrder":2,"ID":62},
{"Explanation":"Item3's text.","Label":"Item3's Label","MsgConfirm":null,"PriceToAdd":295,"TaxExempt":false,"PercentToAdd":0,"SortOrder":3,"ID":63},
{"Explanation":"Item4's text.","Label":"Item4's Label","MsgConfirm":null,"PriceToAdd":395,"TaxExempt":false,"PercentToAdd":0,"SortOrder":4,"ID":64},
{"Explanation":null,"Label":"[foo]","MsgConfirm":null,"PriceToAdd":150,"TaxExempt":false,"PercentToAdd":0,"SortOrder":99,"ID":9}
];

谢谢

4

2 回答 2

1

在使用 Knockout 之前,您不需要展平对象。ko.mapping 插件将创建具有可观察属性的视图模型,并且可以处理复杂的嵌套对象。

要将其与 ASP.NET MVC 模型一起使用,请使用 @Html.Raw() 和 Json 序列化程序(在本例中为Json.NET

function AppViewModel() {
    var self = this;
    self.items = ko.mapping.fromJS(@Html.Raw(JsonConvert.SerializeObject(Model.Items)));
}

ko.applyBindings(new AppViewModel());

从那里,您可以使用 foreach:

<table>
    <tbody data-bind="foreach: items">
        <tr>
            <td data-bind="text: PriceToAdd()"></td>
        </tr>
    </tbody>
</table>
于 2012-11-29T23:54:38.170 回答
0

你可以选择任何一种方式。使用 Razor 在服务器上渲染它,或者在客户端使用淘汰赛渲染它......更基本的问题是你想在哪里渲染它。这里没有正确或错误的答案。

如果您选择淘汰赛,您需要处理的不仅仅是让服务器可能使您的模型变平。Knockout 将需要 ajax 请求来读取然后保存您的数据,这是两种解决方案根本不同的地方

如果您正在考虑将敲除简单地用作客户端模板引擎,那么像jsrender这样的东西可能是一个更好的解决方案。

于 2012-11-29T23:31:44.437 回答