我花了最后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
。对无关元素的单击绑定将此observable设置为false(如果它们都不显示)或添加/替换/删除,具体取决于应显示哪个。一次只能显示一个.manageOption
。
但是,只有当self.managementState
从 false
或转到 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);
});
}
}
从根本上说,这是因为我根本不理解“订阅”的概念。我自己编写绑定的经验很少。如何使用上面的订阅函数来跟踪observable的先前值,以及如何构建我的绑定以实现我需要的?
答案 0 :(得分:1)
第一个问题是您在更新回调中设置订阅。更改某些依赖项时会调用更新函数。所以订阅beforechange事件为时已晚。此外,您还会在每次更改值后设置新订阅。您必须在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);
});
}
}