使用Knockout Mapping显示嵌套的JSON数据

Wei*_*Hao 3 json knockout-mapping-plugin knockout-2.0 knockout.js

我试图在嵌套的JSON对象上使用Knockout的映射插件,里面有可变数据.但是,我不确定如何在HTML中显示它.如何正确映射所有嵌套的JSON对象并将其显示为简单的字符串?这是我的代码:

JS

var ListModel = function(jsonData) {
  var self = this;
  self.master = ko.mapping.fromJS(jsonData);
}
var listModel = new ListModel(jsonData);
ko.applyBindings(listModel);
Run Code Online (Sandbox Code Playgroud)

HTML

<!-- ko foreach: master -->
  <div data-bind="text: $data"></div> 
<!-- /ko -->
Run Code Online (Sandbox Code Playgroud)

示例JSON

{"Level 1a":"Hi","Level 1b":{
  "Level 2a":"Hello","Level 2b":{
    "Level 3":"Bye"}
  }
}
Run Code Online (Sandbox Code Playgroud)

样本输出

Hi
  Hello
    Bye
Run Code Online (Sandbox Code Playgroud)

我在这里要做的主要是打印出所有嵌套级别的值.关键值和嵌套级别的数量是完全可变的(我在SO和在线上找到的大多数嵌套JSON示例都是固定密钥).这可能吗?

更新:我发现jQuery等价,但我仍然需要针对observable的Knockout实现.

Tom*_*lak 5

由于您的JSON对象具有可变键,因此您必须首先将其转换为固定的可预测结构,否则嵌套模板映射将无效(敲除是声明性的,因此您需要事先知道键名).

考虑以下自定义映射代码(不需要淘汰映射插件):

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());
}
Run Code Online (Sandbox Code Playgroud)

该函数nestedMapping()将改变您的数据结构:

{
    "Level 1a": "Hi",
    "Level 1b": {
        "Level 2a": "Hello",
        "Level 2b": {
            "Level 3": "Bye"
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

成:

[
    {
        "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"
                    }
                ]
            }
        ]
    }
]
Run Code Online (Sandbox Code Playgroud)

现在您可以创建一个这样的模板:

<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>
Run Code Online (Sandbox Code Playgroud)

看它工作:http://jsfiddle.net/nwdhJ/2/

请注意一个微妙但重要的观点nestedMapping().它创建了嵌套的observables/observableArrays.但它适用于本数组实例(通过传递self.master()value()进入递归).

这样可以避免在对象构造过程中出现不必要的延迟 每次将值推送到observableArray时,它都会触发敲除更改跟踪,但我们不需要这样做.使用本机数组会快得多.