我有一个网页,从服务器获取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
}
这是我的问题:我想更改一些变量,例如StationId
或StartTime
,EndTime
,然后通过调用{{1}从服务器中提取新数据}}。这部分工作并且接收到数据,但是UI完全搞砸了,可能是因为viewModel的结构变化很大,每行中行数不同,值不同。
所以我需要的是某种UI 重置,可以这么说。换句话说:当新数据到达时,UI应设置为与页面最初加载时相同的状态。之后,可以调用loadData()
和ko.mapping
。
我当然可以重新加载页面,但我真的想避免这种情况。解决此问题的最佳方法是什么?非常感谢!
答案 0 :(得分:0)
你应该在两个独立的部分中破解代码。
ko.applyBinding
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;