将C#循环重构为Knockout映射插件



当服务器向客户端发送一个复杂对象,目标是从C#的'reach'转换到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)与其他项目有不同的元素。

也许我需要研究mapper的一个更先进的用法?

格式化输出比较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}
];

thx

在使用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>

您可以选择任何一种方式。用Razor在服务器上渲染它,或者用knockout在客户端上渲染它。。。更根本的问题是你想把它呈现在哪里。这里没有正确或错误的答案。

如果你选择淘汰,你需要处理的不仅仅是服务器可能会使你的模型变平。Knockout将需要ajax请求来读取和保存您的数据,这就是两种解决方案根本不同的地方。我不认为任何JavaScript是您的解决方案的一部分,如果没有该组件,提供ko解决方案是非常不可能的。

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

最新更新