由于您的 JSON 对象具有可变键,因此您必须首先将其转换为固定的、可预测的结构,否则嵌套模板映射将不起作用(knockout 是声明性的,因此您需要事先知道键名)。
考虑以下自定义映射代码(不需要淘汰映射插件):
var ListModel = function(jsonData) {
var self = this;
self.master = ko.observableArray([]);
function nestedMapping(data, level) {
var key, value, type;
for (key in data) {
if (data.hasOwnProperty(key)) {
if (data[key] instanceof Object) {
type = "array";
value = ko.observableArray([]);
nestedMapping(data[key], value());
} else {
type = "simple";
value = ko.observable(data[key]);
}
level.push({key: key, type: type, value: value});
}
}
}
nestedMapping(jsonData, self.master());
}
该函数nestedMapping()
转换您的数据结构:
{
"Level 1a": "Hi",
"Level 1b": {
"Level 2a": "Hello",
"Level 2b": {
"Level 3": "Bye"
}
}
}
进入:
[
{
"key": "Level 1a",
"type": "simple",
"value": "Hi"
},
{
"key": "Level 1b",
"type": "array",
"value": [
{
"key": "Level 2a",
"type": "simple",
"value": "Hello"
},
{
"key": "Level 2b",
"type": "array",
"value": [
{
"key": "Level 3",
"type": "simple",
"value": "Bye"
}
]
}
]
}
]
现在您可以创建一个像这样的模板:
<script type="text/html" id="nestedTemplate">
<!-- ko if: type == 'simple' -->
<div class="name" data-bind="text: value, attr: {title: key}"></div>
<!-- /ko -->
<!-- ko if: type == 'array' -->
<div class="container" data-bind="
template: {
name: 'nestedTemplate',
foreach: value
}
"></div>
<!-- /ko -->
</script>
看到它工作:http: //jsfiddle.net/nwdhJ/2/
请注意关于nestedMapping()
. 它创建嵌套的 observables/observableArrays。但它适用于本机数组实例(通过传递self.master()
并value()
进入递归)。
这样您就可以避免在对象构造过程中出现不必要的延迟。每次将值推送到 observableArray 时,它都会触发淘汰更改跟踪,但我们不需要这样做。使用本机阵列会快得多。