自定义的剔除绑定会意外触发两次 [英] Custom knockout binding fires twice, unexpectedly

查看:86
本文介绍了自定义的剔除绑定会意外触发两次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了一个自定义绑定处理程序,将我的viewmodel数据绑定到highcharts图表.这实际上有两个部分,一个部分绑定了图表的必需的初始配置,第二个部分则将系列绑定到了图表.

I have written a custom binding handler to bind my viewmodel data to a highcharts chart. This really has 2 parts, one binds the initial config required for highcharts, the second binds the series to the chart.

这是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的可观察数组时,它仅更新图表一次.查看此小提琴,并在单击添加"按钮时观看控制台.您将获得的输出是

Now I have 2 tests set up for this, the first works as expected. It binds a chart with multiple series, and when I add to the observable array bound to the series it updates the chart just once. Look at this fiddle and watch the console as you click the "add" button. The output you'll get is

更新容器对象{chart = {...}}
seriesUnwrapped容器[对象{name ="Scenario0",color ="red",数据= [9]},对象{name ="Scenario1",color ="green",数据= [9]}]

update container Object { chart={...}}
seriesUnwrapped container [Object { name="Scenario0", color="red", data=[9]}, Object { name="Scenario1", color="green", data=[9]}]

表明我们只经历了上面的代码一次.

Indicating that we've been through the above code only once.

现在检查我的第二个小提琴: http://jsfiddle.net/8j6e5/9/.这与highcharts的初始配置和其他系列一样是可以观察到的computed,因此略有不同.当您单击该按钮上的添加"按钮时,您将看到绑定执行了两次:

Now check my second fiddle: http://jsfiddle.net/8j6e5/9/ . This is slightly different as the highcharts initial config is a computed observable, as is the series. When you click the "add" button on this one you'll see the binding is executed twice:

更新container2对象{chart = {...},xAxis = {...},series = [1]}
seriesUnwrapped container2 [对象{name ="Scenario2",color ="blue",data = [2]}]
更新container2对象{chart = {...},xAxis = {...}}
seriesUnwrapped container2 [对象{name ="Scenario2",color ="blue",data = [2]}]

update container2 Object { chart={...}, xAxis={...}, series=[1]}
seriesUnwrapped container2 [Object { name="Scenario2", color="blue", data=[2]}]
update container2 Object { chart={...}, xAxis={...}}
seriesUnwrapped container2 [Object { name="Scenario2", color="blue", data=[2]}]

我猜想在我的highcharts绑定处理程序中使用allBindings.get('series')时,我建立了对它的依赖关系,并且当两个绑定都更改了它的绑定时,执行两次highcharts绑定.我的问题是,是否有任何方法可以阻止这种情况发生,或者以其他方式编写此功能以免发生这种情况?

I'm guessing that using allBindings.get('series') within my highcharts binding handler I set up a dependency to it, and when both bindings change its executing the highcharts binding twice. My question is, is there any way to stop this, or write this functionality any other way as to not have this happen?

推荐答案

您会获得两次更新,因为当依赖项发生变化时,淘汰赛更新会立即计算可观测对象,并且您的绑定具有两个依赖关系,每个依赖关系都会依次更新.

You get two updates because Knockout updates computed observables immediately when their dependencies change, and your binding has two dependencies, each of which gets updated in turn.

解决此问题的一种方法是使用一种技术来延迟绑定的更新.一种简单的方法是使用延迟更新插件,如此处所示: http://jsfiddle.net/mbest/8j6e5/15/

One way to solve this is to use a technique to delay updates of the binding. An easy way to do so is to use the Deferred Updates plugin, as demonstrated here: http://jsfiddle.net/mbest/8j6e5/15/

延迟更新使用setTimeout来执行更新,这意味着更新是异步发生的.如果希望它对于特定更新是同步的,则可以使用ko.tasks.processImmediate:

Deferred Updates uses setTimeout to perform updates, which means that the update happens asynchronously. If you want it to be synchronous for a specific update, you can use ko.tasks.processImmediate:

ko.tasks.processImmediate(function() {
    self.scenarios.push(newScenario);
    self.currentScenario(newScenario);
});            

这篇关于自定义的剔除绑定会意外触发两次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆