【问题标题】:Knockout JS Iterate a array of object using JSONKnockout JS 使用 JSON 迭代一个对象数组
【发布时间】:2018-06-30 09:07:18
【问题描述】:

以下是我的 JSON 响应。我需要使用敲除 foreach 来遍历这个数组并将这个数组显示为手风琴。在这种情况下,“Nissan”将是手风琴标题并单击它展开以显示其他详细信息。我找不到打印键(“Nissan”或“Ford”)并正确创建手风琴的方法。它将是一个动态数组,键会有所不同。我认为我需要嵌套的 foreach 并在迭代第二个时遇到问题。提前致谢。

  var ViewModel = function() {
    var self = this;
    this.entries =
       {
        "Nissan": [
            {"model":"Sentra", "doors":4},
            {"model":"Maxima", "doors":4}
        ],
        "Ford": [
            {"model":"Taurus", "doors":4},
            {"model":"Escort", "doors":4}
        ]
}
    ;


<table>
<tbody data-bind="foreach: entries">
    <tr>
        <td data-bind="foreach: $parent.data()">
            <a href="#" data-bind="text: model"></a>
        </td>
    </tr>
</tbody>
</table>

Fiddle

【问题讨论】:

    标签: javascript arrays json knockout.js


    【解决方案1】:

    JSON 数据使用一个对象将品牌映射到一系列模型,即“Nissan”-> [...]、“Ford”-> [...]。通常在处理这种数据时,我使用 ko.computed() 将对象映射转换为对象数组,通常会添加必要的函数和 observables。

    我使用嵌套列表而不是表格发布了JSFiddle here。点击品牌可展开/折叠车型子列表。

    <ul data-bind="foreach: entries">
      <li>
        <a href="javascript:void(0)" data-bind="text: brand, click: toggle"></a>
        <ul data-bind="foreach: models, visible: visible">
          <li data-bind="text: model"></li>
        </ul>
      </li>
    </ul>
    

    此外,在迭代对象的属性时不能保证顺序。在下面的代码中,对列表进行了排序以确保顺序一致。最佳实践也是使用 hasOwnProperty 检查属性是否在对象上,并且在将对象用作映射时没有从原型链继承。

    还请注意,我将 JSON 响应粘贴到 observable 中,然后在计算后的 observable 中生成条目列表。这确保了如果设置了新的 JSON 数据,计算出的 observable 将自动更新。

    var ViewModel = function() {
    var self = this;
    self.cars = ko.observable({
      "Nissan": [{
        "model": "Sentra",
        "doors": 4
      }, {
        "model": "Maxima",
        "doors": 4
      }],
      "Ford": [{
          "model": "Taurus",
          "doors": 4
        }, {
          "model": "Escort",
        "doors": 4
      }]
    });
    self.entries = ko.computed(function() {
      var list = [],
      entryVM,
      data = self.cars();
      for (var brand in data) {
        if (data.hasOwnProperty(brand)) {
          entryVM = new EntryViewModel(brand, data[brand]);
          list.push(entryVM);
        }
      }
      return list.sort(function(a, b) {
        if (a.brand < b.brand) {
          return -1;
        }
        if (a.brand > b.brand) {
          return 1;
        }
        return 0;
      });
    });
    };
    

    为每个条目创建一个单独的视图模型EntryViewModel,它封装了值和交互。在这种情况下,切换模型列表的可见性被封装在内部视图模型中,因此主视图模型不需要关注内部视图模型的状态。

    var EntryViewModel = function(brand, models) {
      var self = this;
      self.brand = brand;
      self.models = models;
      self.visible = ko.observable(false);
      self.toggle = function() {
        self.visible(!self.visible());
      }
    

    };

    【讨论】:

      猜你喜欢
      • 2019-05-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-18
      相关资源
      最近更新 更多