如何使用淘汰foreach绑定新数据?

时间:2015-04-24 11:52:21

标签: javascript json html5 knockout.js data-binding

我有一个网页,从服务器获取json数据,并带有ajax请求,如下所示:

function loadData() {
    doughnutData = [];
    $.getJSON('/Report/GetConsumption?StationId=' + Station + '&DataPointId=20507&StartTime=' + StartTime.toISOString() + '&EndTime=' + EndTime.toISOString() + '&IntervalSizeStr=' + IntervalSize, function (data) {
        viewModel = ko.mapping.fromJS(data);
        viewModel.getColorForValue = function (val) {
            value = val / viewModel.MaxGridValue();
            var hue = ((1 - value) * 120).toString(10);
            if (value == 0) return ["rgb(70,70,70)"].join("");
            return ["hsl(", hue, ",100%,50%)"].join("");
        };
        ko.applyBindings(viewModel, document.getElementById('data'));

        for (var i = 0; i < viewModel.Rows().length; i++) {
            doughnutData.push({
                value: viewModel.Rows()[i].ConsumptionTotal().toFixed(2),
                label: viewModel.Rows()[i].RowName()
            });
        }

        var ctx = document.getElementById("chart-area").getContext("2d");
        window.myDoughnut = new Chart(ctx).Doughnut(doughnutData, { responsive: true });
    });
}

这是实际显示数据的HTML部分:

    <div id="data">
        <div id="GridRow" data-bind="foreach: Rows">
            <div>
                <div data-bind="text: RowName()"></div>
                <div data-bind="text:(ConsumptionTotal()!=null?ConsumptionTotal().toFixed(2):ConsumptionTotal()) + ' kWh'" style="font-size:12px;font-weight:bold;font-style:italic;float:right;"></div>
            </div>
            <div style="margin-bottom:5px;">
                <div data-bind="foreach: Values" style="clear:both;">
                    <div class="HeatGridCell" data-bind="attr: { title: (new Date(IntervalStart())).toLocaleString() + ': ' + (Value()!=null?Value().toFixed(2):Value()).toLocaleString() + 'kWh' } ,
                      style: {
                          backgroundColor: $root.getColorForValue(Value()),
                          border: '1px solid ' + $root.getColorForValue(Value()),
                          width: ''+((958/$parent.Values().length)-2) +'px',
                          height: '18px',
                          float: 'left'
                      }">
                    </div>
                </div>
            </div>
        </div>
    </div>

这是我的viewModel的一些示例Json数据:

{  
   "Text":"Energiebetrachtung für Station 2:",
   "Rows":[  
      {  
         "RowName":"Energieverbrauch",
         "StationId":9,
         "DataPointId":20507,
         "ConsumptionTotal":16531.0002,
         "Values":[  
            {  
               "IntervalStart":1420119961659,
               "Value":0
            },
            {  
               "IntervalStart":1420206361659,
               "Value":0
            },
            {  
               "IntervalStart":1420292761659,
               "Value":0
            },
            {  
               "IntervalStart":1420379161659,
               "Value":0
            },
            {  
               "IntervalStart":1420465561659,
               "Value":0
            },
            {  
               "IntervalStart":1420551961659,
               "Value":0
            },
            {  
               "IntervalStart":1420638361659,
               "Value":16.419
            },
            {  
               "IntervalStart":1420724761659,
               "Value":33.7859
            },
            {  
               "IntervalStart":1420811161659,
               "Value":1.0555
            },
            {  
               "IntervalStart":1420897561659,
               "Value":55.0716
            },
            {  
               "IntervalStart":1420983961659,
               "Value":1.5794
            },
            {  
               "IntervalStart":1421070361659,
               "Value":1.5794
            },
            {  
               "IntervalStart":1421156761659,
               "Value":1.5794
            },
            {  
               "IntervalStart":1421243161659,
               "Value":1.5794
            },
            {  
               "IntervalStart":1421329561659,
               "Value":13.7923
            },
            {  
               "IntervalStart":1421415961659,
               "Value":380.2002
            },
            {  
               "IntervalStart":1421502361659,
               "Value":304.2716
            },
            {  
               "IntervalStart":1421588761659,
               "Value":348.5954
            },
            {  
               "IntervalStart":1421675161659,
               "Value":512.8432
            },
            {  
               "IntervalStart":1421761561659,
               "Value":926.8025
            },
            {  
               "IntervalStart":1421847961659,
               "Value":915.4359
            },
            {  
               "IntervalStart":1421934361659,
               "Value":959.0111
            },
            {  
               "IntervalStart":1422020761659,
               "Value":944.8331
            },
            {  
               "IntervalStart":1422107161659,
               "Value":849.0834
            },
            {  
               "IntervalStart":1422193561659,
               "Value":324.6436
            },
            {  
               "IntervalStart":1422279961659,
               "Value":88.0598
            },
            {  
               "IntervalStart":1422366361659,
               "Value":1.3593
            },
            {  
               "IntervalStart":1422452761659,
               "Value":232.3545
            },
            {  
               "IntervalStart":1422539161659,
               "Value":586.8022
            },
            {  
               "IntervalStart":1422625561659,
               "Value":524.1148
            },
            {  
               "IntervalStart":1422711961659,
               "Value":378.3096
            },
            {  
               "IntervalStart":1422798361659,
               "Value":693.6768
            },
            {  
               "IntervalStart":1422884761659,
               "Value":656.1949
            },
            {  
               "IntervalStart":1422971161659,
               "Value":1037.8794
            },
            {  
               "IntervalStart":1423057561659,
               "Value":1241.6998
            },
            {  
               "IntervalStart":1423143961659,
               "Value":1176.4226
            },
            {  
               "IntervalStart":1423230361659,
               "Value":1141.9589
            },
            {  
               "IntervalStart":1423316761659,
               "Value":29.8893
            },
            {  
               "IntervalStart":1423403161659,
               "Value":44.1929
            },
            {  
               "IntervalStart":1423489561659,
               "Value":6.4767
            },
            {  
               "IntervalStart":1423575961659,
               "Value":10.1638
            },
            {  
               "IntervalStart":1423662361659,
               "Value":319.7191
            },
            {  
               "IntervalStart":1423748761659,
               "Value":178.564
            },
            {  
               "IntervalStart":1423835161659,
               "Value":3.3811
            },
            {  
               "IntervalStart":1423921561659,
               "Value":78.1026
            },
            {  
               "IntervalStart":1424007961659,
               "Value":284.9436
            },
            {  
               "IntervalStart":1424094361659,
               "Value":122.8865
            },
            {  
               "IntervalStart":1424180761659,
               "Value":310.0112
            },
            {  
               "IntervalStart":1424267161659,
               "Value":117.0268
            },
            {  
               "IntervalStart":1424353561659,
               "Value":11.1318
            },
            {  
               "IntervalStart":1424439961659,
               "Value":3.0199
            },
            {  
               "IntervalStart":1424526361659,
               "Value":91.8154
            },
            {  
               "IntervalStart":1424612761659,
               "Value":143.7019
            },
            {  
               "IntervalStart":1424699161659,
               "Value":122.9965
            },
            {  
               "IntervalStart":1424785561659,
               "Value":88.1888
            },
            {  
               "IntervalStart":1424871961659,
               "Value":0.7581
            },
            {  
               "IntervalStart":1424958361659,
               "Value":0.7581
            },
            {  
               "IntervalStart":1425044761659,
               "Value":212.2776
            }
         ]
      }
   ],
   "StartDate":1420119961659,
   "EndDate":1425131167601,
   "MinGridValue":0,
   "MaxGridValue":1241.6998
}

这是我的问题:我想更改一些变量,例如StationIdStartTimeEndTime,然后通过调用{{1}从服务器中提取新数据}}。这部分工作并且接收到数据,但是UI完全搞砸了,可能是因为viewModel的结构变化很大,每行中行数不同,值不同。

所以我需要的是某种UI 重置,可以这么说。换句话说:当新数据到达时,UI应设置为与页面最初加载时相同的状态。之后,可以调用loadData()ko.mapping

我当然可以重新加载页面,但我真的想避免这种情况。解决此问题的最佳方法是什么?非常感谢!

1 个答案:

答案 0 :(得分:0)

你应该在两个独立的部分中破解代码。

  1. 视图初始化,您可以在其中设置视图模型对象,并使用ko.applyBinding
  2. 进行绑定
  3. 根据服务器中的数据更新视图模型的部分。
  4. &#13;
    &#13;
    var viewModel;
    
    // View should be setup one time for the application.
    // No need the recreate view model each time when you load data 
    // from the server. It is actually would be performance hit.
    function setupView() {
        viewModel = {
          data: ko.observable(),
          getColorForValue: function (val) {
            value = val / viewModel.MaxGridValue();
            var hue = ((1 - value) * 120).toString(10);
            if (value == 0) return ["rgb(70,70,70)"].join("");
            return ["hsl(", hue, ",100%,50%)"].join("");
          },
    
          // Here the power of KO. Computed properties.
          // Use with caution.
          // This property will be recalculated when you data would be changed.
          // See function below for usage.
          doughnutData: ko.computed(function () {
              var doughnutData = [];
              var rows = viewModel.data().Rows();
              for (var i = 0; i < rows.length; i++) {
                doughnutData.push({
                    value: rows[i].ConsumptionTotal().toFixed(2),
                    label: rows[i].RowName()
                });
              }
              return doughnutData;
          }, this);
        }
        ko.applyBindings(viewModel, document.getElementById('data'));
    }
    
    // This function now could be called multiple times.
    function loadData() {
        $.getJSON('/Report/GetConsumption?StationId=' + Station + '&DataPointId=20507&StartTime=' + StartTime.toISOString() + '&EndTime=' + EndTime.toISOString() + '&IntervalSizeStr=' + IntervalSize, function (data) {
            
            // HERE THE UPDATE OF THE VIEW.
            // The trick is to create special property which will hold the data.
            viewModel.data(ko.mapping.fromJS(data));
    
            // True power of Knockout comes from the computed properties and bindings
            // Below example of using computed properties.
            var doughnutData = viewModel.doughnutData();
    
            var ctx = document.getElementById("chart-area").getContext("2d");
            window.myDoughnut = new Chart(ctx).Doughnut(doughnutData, { responsive: true });
        });
    }
    &#13;
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
        <div id="data" data-bind="with: data">
            <div id="GridRow" data-bind="foreach: Rows">
                <div>
                    <div data-bind="text: RowName()"></div>
                    <div data-bind="text:(ConsumptionTotal()!=null?ConsumptionTotal().toFixed(2):ConsumptionTotal()) + ' kWh'" style="font-size:12px;font-weight:bold;font-style:italic;float:right;"></div>
                </div>
                <div style="margin-bottom:5px;">
                    <div data-bind="foreach: Values" style="clear:both;">
                        <div class="HeatGridCell" data-bind="attr: { title: (new Date(IntervalStart())).toLocaleString() + ': ' + (Value()!=null?Value().toFixed(2):Value()).toLocaleString() + 'kWh' } ,
                          style: {
                              backgroundColor: $root.getColorForValue(Value()),
                              border: '1px solid ' + $root.getColorForValue(Value()),
                              width: ''+((958/$parent.Values().length)-2) +'px',
                              height: '18px',
                              float: 'left'
                          }">
                        </div>
                    </div>
                </div>
            </div>
        </div>
    &#13;
    &#13;
    &#13;