使用敲除渲染并排比较

时间:2016-02-09 00:55:16

标签: javascript twitter-bootstrap knockout.js

我正在开展一个项目,我希望能够并排显示几个项目进行比较。

我希望比较显示的方式与亚马逊的方式类似,每个项目都由一个垂直列表示,其中包含该列中该项目的所有信息:

enter image description here

我目前正在使用Knockout,并且有一个Observable数组,其中包含我想要比较的项目。我想使用foreach绑定来完成这项工作,我的问题源于这样一个事实,即table包含在同一元素中的特定行的所有单元格,这使得它很难使用:

<tr>
  <td>Rating</td>
  <td> 4.5 (data from item 1)</td>
  <td> 3.5 (data from item 2)</td>
</tr>
<tr>
  <td>price</td>
  <td>$2.3 (data from item 1) </td>
  <td>$3.5 (data from item 2) </td>
</td>

如果我希望每个项目都包含在一行中,这不会有问题。 任何人都有任何关于如何解决这个问题的建议,因为不同项目的数据必须存在于文档的不同(重叠)部分。

1 个答案:

答案 0 :(得分:3)

我有个坏消息。 Html表严格按行排序,这种数据布局可能有点令人沮丧。

您有两种选择,基本上:

选项A:转置数据

您可以为&#34;功能比较&#34;介绍特定的视图模型。并将您的数据转换为该数据。然后,您可以在foreach上执行tbody重复这些&#34; featureComparisons&#34;。在代码中,这就是我的意思:

&#13;
&#13;
var inputData = [
  { name: "First product", rating: 4.5, price: "$3.50", color: "Gray" },
  { name: "Another product", rating: 3.5, price: "$2.95", color: "Yellow" }
];

function FeatComparison(comparisonName, comparedValues) {
  this.comparisonName = comparisonName;
  this.comparedValues = comparedValues;
}

var vm = { comparisons: ko.observableArray([]) };

// You could also explicitly send a list of comparable properties from back-end.
// For this example we iterate the first product.
for (var prop in inputData[0]) {
  if (inputData[0].hasOwnProperty(prop)) {
    var vals = inputData.map(function(i) { return i[prop]; });
    vm.comparisons.push(new FeatComparison(prop, vals));
  }
}

ko.applyBindings(vm);
&#13;
td { background: #eee; padding: 5px 10px; }
tr:first-child, td:first-child { font-weight: bold; }
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<table><tbody data-bind="foreach: comparisons">
  <tr>
    <td data-bind="text: comparisonName"></td>
    <!-- ko foreach: comparedValues -->
    <td data-bind="text: $data"></td>
    <!-- /ko -->
  </tr>
</tbody></table>
&#13;
&#13;
&#13;

此选项最适合您希望通过比较多个产品,保存用户对要包含或不包含的功能的用户偏好等内容进行扩展比较功能的情况。

选项B:处理它(缺少更好的标题)

只需按原样保留数据,然后同时使用foreach遍历这两个对象。在代码中:

&#13;
&#13;
var inputData = [
  { name: "First product", rating: 4.5, price: "$3.50", color: "Gray" },
  { name: "Another product", rating: 3.5, price: "$2.95", color: "Yellow" }
];

function RootVm(data) {
  var self = this;
  this.products = ko.observableArray(data);
  this.keys = ko.computed(function() {
    if (self.products().length === 0) return [];
    return Object.keys(self.products()[0]);
  });
}

ko.applyBindings(new RootVm(inputData));
&#13;
td { background: #eee; padding: 5px 10px; }
tr:first-child, td:first-child { font-weight: bold; }
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<table><tbody data-bind="foreach: keys">
  <tr>
    <td data-bind="text: $data"></td>
    <!-- ko foreach: $root.products -->
    <td data-bind="text: $data[$parent]"></td>
    <!-- /ko -->
  </tr>
</tbody></table>
&#13;
&#13;
&#13;