制作自定义crossFadeVisible bindingHandler的问题

时间:2012-10-21 04:33:18

标签: knockout.js

我正在尝试制作一个crossFadeVisible bindingHandler。主要的想法是,当我们设置一个值时,我希望它能够淡入。如果我们清除该值(即设置为null),我想让它淡出,如果我们改变了值,我想让它淡出旧值,然后淡出新值。

我在下午的大部分时间里一直在打架,所以我不完全确定这是可能的。

我决定跟随别人的行为,并为此创建 jsfiddle http://jsfiddle.net/jrstarke/4DTFq/20/)。

最初该值未定义,但是如果您点击Set,我们将值设置为1,并添加一些新按钮。如果您现在清除该值,它将按预期消失,并再次设置它可以正常工作。如果你达到增量,一切都按预期工作。

现在这部分我无法解释。如果显示“2”,则按下增量,没有任何反应。清除,按钮消失(因为我们现在已经清除了原始值)。但显示值保持不变。

我无法解释的是,当我们调用value.displayed(value())将新显示值设置为当前值时,它会立即再次调用更新方法(?)此时我们完全运行该方法,并按预期更新,但看起来我们已经从更改中取消绑定值,因为此更新方法永远不会再次调用。

任何人都知道如何解决这个问题,或者我正在尝试做什么?

1 个答案:

答案 0 :(得分:2)

问题是在第一个fadeOut之后永远不会调用处理程序的更新代码。原因是依赖关系跟踪代码没有检测到您的绑定依赖于value,因为它实际上从未被读取过。因此,当值实际更新时,绑定永远不会被重新触发。

为什么会发生这种情况是因为在更新绑定时不会调用postFade代码。当fadeOut完成后,它实际上会被调用。它会在最初更新时更新,因为在postFade是假的时候调用了value.displayed函数。

解决此问题的一种简单方法是在调用更新代码时在某处读取value。您不一定要对值进行任何操作,只需要尝试阅读它。

update: function(element, valueAccessor) {
    var value = valueAccessor();

    var postFade = function() {
        // postFade depends on `value`
        value.displayed(value());
        if (value.displayed()) $(element).fadeIn('fast');
    }

    if (value.displayed()) {
        // postFade is invoked later after the fade out
        $(element).fadeOut('fast', postFade);
        // dependent on `value.displayed`

        // get the value so the dependency tracking code
        // detects that the binding depends on it
        value();
    }
    else {
        // postFade is invoked immediately
        postFade();
        // dependent on `value.displayed` and `value`
    }
}