我花了最后6个小时来尝试解决此问题,但关于Knockout.js中的订阅如何工作的文献很少,以至于现在它已从“轻度烦人”类别转移到“彻底令人沮丧”类别。

我想完成什么?

我需要为DOM的一部分设置动画,以使其根据需要上下滑动。这是以这种方式动画化的DOM的一般结构:

<section id="add" class="manageOption">
</section>
<section id="replace" class="manageOption">
</section>
<section id="remove" class="manageOption">
</section>


每个.manageOption具有相同的大小和尺寸,并且看起来非常相似。我的ViewModel中有一个名为self.managementState的观察对象,该对象最初设置为false。如果不显示任何元素,则对不相关元素的单击绑定会将此可观察值设置为false,或者根据应显示的内容将其添加/替换/删除。一次只能显示一个.manageOption

但是,仅当self.managementStatefalse变为false时,才会发生slideUp或slideDown效果。因此,我不仅需要知道self.managementState的当前值,还需要知道前一个值。如果值从add更改为remove,则无需为元素设置动画,更改将立即发生。

我尝试过的

为了解决这个问题,我一直想构建一个名为slideSwitcher的自定义绑定,该绑定使用我已经描述的上述逻辑进行操作,并且我还发现这部分代码应该获取可观察对象的先前值:

function subscribeToPreviousValue(observable, fn) {
    observable.subscribe(fn, this, 'beforeChange');
}


但是我无法在自定义绑定中的update函数中很好地发挥它的作用,它总是返回错误的结果(例如,false已更改为false)。

ko.bindingHandlers.slideSwitcher = {
    update: function (element, valueAccessor) {
        var observable = valueAccessor();
        var currentVal = ko.utils.unwrapObservable(valueAccessor());

        subscribeToPreviousValue(observable, function (previous) {
            console.log('value changed from', previous, 'to', currentVal);
        });
    }
}


从根本上讲,这是因为我根本不了解“订阅”的概念,而且我自己编写绑定的经验很少。如何使用上面的订阅函数来跟踪可观察对象的先前值,以及如何构造绑定以实现所需的内容?

最佳答案

第一个问题是您在更新回调中设置了订阅。更改某些依赖项时将调用更新函数。因此,订阅更改前事件为时已晚。此外,您还需要在每次更改值后设置新的订阅。您必须在init函数中订阅该值。

我喜欢subscribeChanged函数(Get previous value of an observable in subscribe of same observable-第二个答案),它很好而且很清楚...

ko.subscribable.fn.subscribeChanged = function (callback) {
    var oldValue;
    this.subscribe(function (_oldValue) {
        oldValue = _oldValue;
    }, this, 'beforeChange');

    this.subscribe(function (newValue) {
        callback(newValue, oldValue);
    });
};


您可以如下编写绑定

ko.bindingHandlers.slideSwitcher = {
    init: function (element, valueAccessor) {
        var observable = valueAccessor();
        observable.subscribeChanged(function (newValue, oldValue) {
            console.log('value changed from', oldValue, 'to', newValue);
        });
    }
}

07-24 09:50
查看更多