将json字符串解析为knockout observables

时间:2017-02-15 13:28:14

标签: javascript json knockout.js

我从REST端点获得以下响应,我需要使用值填充字典。 json看起来像这样:{" name":" A"," id:" A"," properties":{ "说明":" A","文字":" A","号码":"一个& #34;}}最终,我将获得这个json对象的数组。

我在我的ajax成功回调中尝试了以下内容:

    console.log(result)
        for (x in result){
            console.log(result[x])
            if (x  === 'object'){
                for (y in x){
                    console.log(x[y]);
                }
            }
        }

这真的不是我想要的。如果用户选择名称,我需要能够将属性值加载到knockout变量中。

1 个答案:

答案 0 :(得分:0)

我认为你的问题有两个方面:

  • 将数据从json字符串转换为视图模型
  • 管理用户界面并确保它可以处理(外部)数据更改而不会丢失状态

将json转换为viewmodel

这可以自动完成(例如,通过评论中链接的ko-mapping插件),也可以手动完成。我赞成手动映射。基础知识:

  1. 解析JSON。

    例如:从'{ "name": "A" }'{ name: "A" }

  2. 通过prototypeobservablecomputed属性添加功能。

    例如:从{ name: "A" }{ name: ko.observable("A"), index: 0, /* ... */ }

  3. 管理国家和地区外部数据变更

    一旦创建了一组视图模型,您就需要一个地方来管理选择。基础知识:

    this.items = ko.observableArray([ { name: "A" }, { name: "B" } ]);
    this.selection = ko.observable(items[0]);
    

    您可以将项目和选择数据绑定到UI。例如,使用<select>元素:

    <select data-bind="options: items, optionsText: 'name', value: selection></select>
    

    这样就完成了链:json&gt; array of objects&gt; array of viewmodels + selected viewmodel reference

    现在,唯一的挑战是确保您可以从服务器重新加载数据而不会丢失选择。为此,您可以向viewmodel添加update方法来设置可观察属性,或者替换所有视图模型并存储选定的id而不是对对象的引用。

    一起作为例子:

    var createItem = function (obj) {
      // Up to you how you map to "viewmodels", 
      // If you want two-way binding (for editing),
      // wrap in an observable.
      // Example for 1-way binding
      return Object.assign({
        name: obj.name,
        id: obj.id,
        randomNr: Math.random()
      }, Object.keys(obj.properties).reduce(function(res, key) {
        res[key] = obj.properties[key];
        return res;
      }, {}));
    };
    
    var VM = function() {
      this.rawData = ko.observableArray([]);
    
      // Create "item" view models from the array of objects
      this.items = ko.pureComputed(function() {
        return this.rawData().map(createItem);
      }, this);
      
      // Store items by `id` prop. (Could also be a plain object)
      var itemMap = ko.pureComputed(function() {
        return new Map(
          this.items().map(function(item) {
            return [item.id, item];
          })
        );
      }, this);
      
      // Store the id of the selected item
      this.selectedId = ko.observable(null);
      
      // Whenever either the selected id, _or_ the  array of items changes,
      // update the selected item
      this.selectedItem = ko.pureComputed(function() {
        return itemMap().get(this.selectedId());
      }, this);
      
    };
    
    VM.prototype.loadData = function(json) {
      // Hardcoded
      json = '[{"name":"A", "id":"A", "properties":{"description":"A", "text":"A", "number":"one"}}, {"name":"B", "id":"B", "properties":{"description":"B", "text":"B", "number":"two"}},{"name":"C", "id":"C", "properties":{"description":"C", "text":"C", "number":"three"}}]';
      
      // Might want to wrap in a try catch
      this.rawData(JSON.parse(json));
    }
    
    var vm = new VM();
    ko.applyBindings(vm);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
    
    
    <select data-bind="options: items, 
                       optionsText: 'name', 
                       optionsValue: 'id',
                       value: selectedId"></select>
    
    <p>Your selection:<p>
    <div data-bind="with: selectedItem">
      <h3>Name: <span data-bind="text: name"></span></h3>
      <h4>Description:<span data-bind="text: description + randomNr"></span></h4>
      <p>Nr:<span data-bind="text: number"></span></p>
    </div>
    <button data-bind="click: loadData">load data</button>