我刚刚开始使用knockoutjs,我正在尝试构建动态树视图。为简化起见,我删除了与问题无关的所有内容。树视图将由嵌套的UL标签组成。
html:
<div id="pnlDestinations">
<ul data-bind="template: { name: 'GroupTemplate', foreach: Groups }"></ul>
</div>
<script type="text/html" id="GroupTemplate">
<li>
<a href="#" data-bind="text: GroupName, click: function() { RetrieveDestinations($data); }"></a>
<ul data-bind="template: { name: 'DestinationTemplate', foreach: Destinations }"></ul>
</li>
</script>
<script type="text/html" id="DestinationTemplate">
<li>
<a href="#" data-bind="text: DestinationName"></a>
</li>
</script>
代码:
function ViewModel(groups) {
Groups = ko.mapping.fromJS(groups);
RetrieveDestinations = function (group) {
$.getJSON('GetDestinations?id=' + group.GroupId(), function (data) {
group.Destinations(ko.mapping.fromJS(data));
});
}
}
$(function () {
$.getJSON("GetGroups", function (data) {
ko.applyBindings(new ViewModel(data));
});
});
所以我在两个级别绑定树视图(使用2个模板),但我只检索“GetGroups”中的一个级别(Destinations存在,但是是一个空数组)。
单击组时,将在RetrieveDestinations()方法中检索目标,并应替换组中的空数组。但是,它们并没有显示在我的树视图中。
树视图的绑定应该是正确的,因为如果我在“GetGroups”中包含目标,则所有内容都会正确呈现。
答案 0 :(得分:3)
ko.mapping.fromJS
给定数组时会将其转换为observableArray。
因此,当您执行group.Destinations(ko.mapping.fromJS(data))
时,您将Destinations
observableArray的值设置为等于observableArray。基本上,这只意味着它被包裹了两次。
您可以执行group.Destinations(ko.mapping.fromJS(data)())
jsFiddle目前不允许保存,但是这里简化了您的代码以使用映射插件来更新目标(setTimeouts来模拟AJAX):
<div id="pnlDestinations">
<ul data-bind="foreach: Groups">
<li>
<a href="#" data-bind="text: GroupName, click: $root.RetrieveDestinations"></a>
<ul data-bind="foreach: Destinations">
<li>
<a href="#" data-bind="text: DestinationName"></a>
</li>
</ul>
</li>
</ul>
</div>
视图模型:
function ViewModel(groups) {
this.Groups = ko.mapping.fromJS(groups);
this.RetrieveDestinations = function (group) {
setTimeout(function() {
//fake data
var name = group.GroupName(),
data = [
{ DestinationName: name + "-1" },
{ DestinationName: name + "-2" },
{ DestinationName: name + "-3" }
];
ko.mapping.fromJS(data, {}, group.Destinations);
group.Destinations.push({ DestinationName: "new" });
}, 100);
};
}
$(function () {
setTimeout(function() {
var data = [
{ GroupName: "Group1", Destinations: [] },
{ GroupName: "Group2", Destinations: [] },
{ GroupName: "Group3", Destinations: [] }
];
ko.applyBindings(new ViewModel(data));
}, 100);
});