使用knockout.js来跨列绑定javascript关联数组

asp.net mvc 4 - Use knockout.js to data-bind javascript associative array across columns

本文关键字:绑定 javascript 关联 数组 knockout js 使用      更新时间:2023-09-26

在c# DestopModel.cs中,我们定义了一个DesktopViewModel,其中包含了许多设计。

public class DesktopViewModel
{
        public Guid Id { get; set; }              
        public List<DesktopDesignViewModel> Designs { get; set; }
        // ...
}

在脚本中。在cshtml中,我们已经将DesktopViewModel转换为击倒视图模型。我们还有一个DesignScore函数,它执行一些计算并返回一组分数对于每个设计跨多个类别。

@model DesktopViewModel
<script type="text/javascript">
    var Desktop = {
        ViewModel: null,
        Initialize: function () {
            // create knockout model
            Desktop.ViewModel = ko.mapping.fromJS(@Html.Raw(Json.Encode(Model)));
            // ...
            this.ViewModel.DesignScore = function (design) {
                return ko.computed(function () {
                    var ClimateChange = 0;
                    var OceanAcidification = 0;
                    var OzoneDepletion = 0;
                    var BiogeochemicalCycles = 0;
                    var FreshWaterUse = 0;
                    var ChangeInLandUse = 0;
                    var BiodiversityLoss = 0;
                    var ChemicalPollution = 0;
                    var AtmosphericAerosols = 0;
                    // ... some calculations
                    return {
                        "ClimateChange": ClimateChange,
                        "OceanAcidification": OceanAcidification,
                        "OzoneDepletion": OzoneDepletion,
                        "BiogeochemicalCycles": BiogeochemicalCycles,
                        "FreshWaterUse": FreshWaterUse,
                        "ChangeInLandUse": ChangeInLandUse,
                        "BiodiversityLoss": BiodiversityLoss,
                        "ChemicalPollution": ChemicalPollution,
                        "AtmosphericAerosols": AtmosphericAerosols
                    };
                });
            }
        }
    }
</script>

在我们看来。cshtml,我试图在一个表中显示结果。

                        des1    des2    des3
=================================================
Climate Change          1560    936     3588
Ocean Acidification     1560    936     3588
Ozone Depletion         0.1     0.2     0.3
...

下面是我当前对结果进行数据绑定的方式:

<table>
    <thead>
        <tr>
            <th class="col-md-2 text-center">&nbsp;</th>
            <!-- ko foreach: Designs -->
            <th class="text-center">
                <h5 data-bind="text: Name"></h5>
            </th>
            <!-- /ko -->
        </tr>
    </thead>
    <tbody>
        <tr class="top-border-row">
            <td class="text-center">
                <h4>Climate Change</h4>
            </td>
            <!-- ko foreach: { data: $root.Designs, as: 'design' } -->
            <td class="text-center">                                                                
                <h4 data-bind="text: $root.DesignScore(design)().ClimateChange"></h4>
            </td>
            <!-- /ko -->                            
        </tr>
        <tr class="top-border-row">
            <td class="text-center">
                <h4>Ocean Acidification</h4>
            </td>
            <!-- ko foreach: { data: $root.Designs, as: 'design' } -->
            <td class="text-center">                                                                
                <h4 data-bind="text: $root.DesignScore(design)().OceanAcidification"></h4>
            </td>
            <!-- /ko -->                            
        </tr>
        // ...                            
    </tbody>
</table>

现在,我正在迭代每个类别的每个设计,并在我的数据绑定中调用DesignScore九次,尽管对DesignScore函数的一次调用将返回所有类别的所有结果。

问题:是否有一种方法可以通过每个设计查询一次,并将结果跨类别按列绑定?HTML只有tr元素,但没有tc。

UPDATE1:

我将DesignScore函数拆分为单独的函数,并将每个函数的结果数据绑定到一个knockout模板中。结果表只有一列。

输出:

des1  des2  des3
==================
1560 (ie. des1's Climate Change)
0.1  (ie. des1's Ozone Depleition)
3900.7 (ie. des2's Climate Change)
0.2
3588.6
0.3
代码:

<table>
<thead>
    <tr>
        <th class="col-md-2 text-center">&nbsp;</th>
        <!-- ko foreach: Designs -->
        <th class="text-center">
            <h5 data-bind="text: Name"></h5>
        </th>
        <!-- /ko -->
    </tr>
</thead> 
<tbody data-bind="template: { name: 'impact-category-template', foreach: $root.Designs, as: 'design' }"></tbody>
</table>
<script type="text/html" id="impact-category-template">    
      <tr>
          <td class="text-center"> 
              <h4 data-bind="text: $root.ClimateChange(design)"></h4>
          </td>
      </tr>
      <tr>
          <td class="text-center"> 
                  <h4 data-bind="text: $root.OzoneDepletion(design)"></h4>
          </td>
      </tr>
</script>

这真的不应该那么难。我不完全掌握你的数据模型,但我会尝试建模每一行作为一个对象,并使用模板来呈现它。尽量简化。

关于计算,每个类别是否相似?如果它被调用一次,我认为不需要计算。

function DesktopDesignViewModel() {
  var self = this;
  self.categoryName= ko.observable();
  self.dest1= ko.observable();
  self.dest2= ko.observable();
  self.dest3= ko.observable();
  //may be used as constructor to fill in observables
  self.superCalc = function(){}; 
}

<script id="resultsTemplate" type="text/html">
   <tr>
       <td data-bind="text: categoryName"></td>
       <td data-bind="text: dest1"></td>
       <td data-bind="text: dest2"></td>
       <td data-bind="text: dest3"></td>
   </tr>
</script>
<table>
  <thead>
     <tr>
       <th>Name</th>
       <th>Dest1</th>
       <th>Dest2</th>
       <th>Dest3</th>
    </tr>
    </thead>
      <tbody data-bind="template: { name: 'resultsTemplate', foreach: Designs}"></tbody>
</table>