【发布时间】:2014-02-11 13:09:49
【问题描述】:
我编写了一个自定义绑定处理程序来将我的视图模型数据绑定到一个 highcharts 图表。这实际上有两部分,一个绑定 highcharts 所需的初始配置,第二个将系列绑定到图表。
这里是bindingHandler 代码
ko.bindingHandlers.highchart = {
update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
var value = valueAccessor();
var valueUnwrapped = ko.unwrap(value);
console.log ('update',element.id,valueUnwrapped);
if(allBindings.get('series')){
var series = allBindings.get('series');
var seriesUnwrapped = ko.unwrap(series);
if(!$.isArray(seriesUnwrapped)){
seriesUnwrapped = [seriesUnwrapped];
}
console.log('seriesUnwrapped',element.id,seriesUnwrapped)
valueUnwrapped.series = seriesUnwrapped;
}
$(element).highcharts(valueUnwrapped);
}
}
现在我为此设置了 2 个测试,第一个按预期工作。它绑定了一个具有多个系列的图表,当我添加到绑定到series 的可观察数组时,它只更新一次图表。查看this fiddle 并在单击“添加”按钮时观察控制台。你会得到的输出是
更新容器对象 { chart={...}}
seriesUnwrapped 容器 [Object { name="Scenario0", color="red", data=[9]}, Object { name="Scenario1", color="green", data=[9]}]
表示我们只经历过上述代码一次。
现在检查我的第二个小提琴:http://jsfiddle.net/8j6e5/9/。这略有不同,因为 highcharts 初始配置是 computed 可观察的,系列也是如此。当您单击此按钮上的“添加”按钮时,您会看到绑定执行了两次:
更新 container2 对象 { chart={...}, xAxis={...}, series=[1]}
seriesUnwrapped container2 [Object { name="Scenario2", color="blue", data=[2]}]
更新 container2 对象 { chart={...}, xAxis={...}}
seriesUnwrapped container2 [Object { name="Scenario2", color="blue", data=[2]}]
我猜想在我的 highcharts 绑定处理程序中使用allBindings.get('series') 我设置了对它的依赖,并且当两个绑定都更改时,它执行 highcharts 绑定两次。我的问题是,有没有办法阻止这种情况,或者以任何其他方式编写此功能以防止这种情况发生?
【问题讨论】:
-
您必须决定何时调用更新函数。因此,当您的绑定属性更改或
series绑定属性更改时。然后使用peek()而不是ko.unwrap:var seriesUnwrapped = series.peek();或var valueUnwrapped = value.peek();您当然需要检查以测试value或series在调用peek 之前确实是可观察的。 -
@nemesv - 这是一个非常好的开始,仅此一项就解决了双重通话问题。然而,在进行了简单的更改之后,我的第一个小提琴将不再更新(因为它绑定到一个计算系列,但一个静态的 highchart 属性)。你距离一个非常好的答案只有 2/3。
-
如果你使用值
var valueUnwrapped = ko.isObservable(value) ? value.peek() : value;来解决这两个问题。但是,如果您的绑定是highchart: yourProp, series: otherProp并且只有yourProp发生变化,而otherProp没有变化,那么它就不会正确更新您的图表...
标签: javascript knockout.js bindinghandlers