在 "beforeChange" 订阅中获取可观察对象的新值
Get new value of an observable in "beforeChange" subscription
我知道 get the new value of an observable in a subscribe event 有解决方案(在实际更改之后),但我想知道是否可以在 "beforeChange" 订阅中访问可观察对象的新值。
下面是 current version of Knockout (3.4.1) 分别使用旧值和新值引发 beforeChange 和 afterChange 订阅处理程序的片段:
if (computedObservable.isDifferent(state.latestValue, newValue)) {
if (!state.isSleeping) {
computedObservable["notifySubscribers"](state.latestValue, "beforeChange");
}
state.latestValue = newValue;
if (DEBUG) computedObservable._latestValue = newValue;
if (state.isSleeping) {
computedObservable.updateVersion();
} else if (notifyChange) {
computedObservable["notifySubscribers"](state.latestValue);
}
changed = true;
}
显然 newValue 在 "beforeChange" 可用,所以我想分叉是一种选择,但我不想这样做。
是否有任何其他解决方案来获得这个新值"beforeChange"?
编辑:我刚刚重读了你的问题,我想你可能是想在 设置之前检查新值?如果是这种情况,您可能想要执行类似 this.
的操作
我通常创建两个订阅和一个额外的变量来跟踪旧的(您可能已经尝试过):
var myObs = ko.observable(1);
// Keep track of old
var myObsOld = myObs();
myObs.subscribe(function(oldVal) {
myObsOld = oldVal;
}, null, "beforeChange");
// Subscribe to new
myObs.subscribe(function(newVal) {
console.log("myObs changed from", myObsOld, "to", newVal);
});
myObs(2);
myObs(3);
.as-console-wrapper { min-height: 100%; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
现在,如果您不想在视图模型中乱放额外的变量和订阅,您可以将此逻辑封装在扩展程序中:
ko.extenders.latestValue = function(target, option) {
target.latestValue = target();
target.subscribe(function(oldVal) {
target.latestValue = oldVal;
}, null, "beforeChange");
return target;
};
var myObs2 = ko.observable("a").extend({ latestValue: true });
myObs2.subscribe(function(newVal) {
console.log("myObs2 changed from", myObs2.latestValue, "to", newVal);
});
myObs2("b");
myObs2("c");
.as-console-wrapper { min-height: 100%; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
这不是一个非常性感的方法,但我认为它比分叉回购更好 :)
注意:此答案基于您对问题的评论而非原始问题。
当一个 observable 发生变化时,它会在该 observable 上调用一个名为 notifySubscribers
的方法,该方法会执行实际的通知,从而更新依赖于该 observable 的任何计算的 observable、绑定等。如果您想在任何这些通知之前执行某些操作,您有几种选择。
如@user3297291 所述,使用 Ryan Niemeyer 的 protectedObservable。
立即订阅可观察对象,然后再进行任何其他订阅。始终按顺序调用订阅者,因此您的代码将始终 运行 优先于其他任何内容。
Override notifySubscribers
hook into the notification process (记得调用之前的方法)
可能对于 Knockout 3.5.0,在 change
事件之前会有 a spectate
event。
这并不完全是对您请求的回应,但可能对略有不同的用例有用。
如果您不坚持在更改传播到可观察对象之前调用订阅并与 beforeChange 订阅一起触发,则可以创建自己的订阅,将旧值和新值一起推送到回调。
此订阅在更改发生后触发,它只是同时提供以前和当前的值。
/**
* extended version of knockout subscription provides to callback function new and previous value at once
* function Callback(newValue, originalValue) {...}
*
* @param {Function} callback function called on observable change
* @param {Object} context of the callback
* @return {Object} instance of changed subscription
*/
ko.subscribable.fn.subscribeChanged = function (callback, context) {
var savedValue = this.peek();
return this.subscribe(function (latestValue) {
var oldValue = savedValue;
savedValue = latestValue;
callback(latestValue, oldValue);
}, context);
};
我知道 get the new value of an observable in a subscribe event 有解决方案(在实际更改之后),但我想知道是否可以在 "beforeChange" 订阅中访问可观察对象的新值。
下面是 current version of Knockout (3.4.1) 分别使用旧值和新值引发 beforeChange 和 afterChange 订阅处理程序的片段:
if (computedObservable.isDifferent(state.latestValue, newValue)) {
if (!state.isSleeping) {
computedObservable["notifySubscribers"](state.latestValue, "beforeChange");
}
state.latestValue = newValue;
if (DEBUG) computedObservable._latestValue = newValue;
if (state.isSleeping) {
computedObservable.updateVersion();
} else if (notifyChange) {
computedObservable["notifySubscribers"](state.latestValue);
}
changed = true;
}
显然 newValue 在 "beforeChange" 可用,所以我想分叉是一种选择,但我不想这样做。
是否有任何其他解决方案来获得这个新值"beforeChange"?
编辑:我刚刚重读了你的问题,我想你可能是想在 设置之前检查新值?如果是这种情况,您可能想要执行类似 this.
的操作我通常创建两个订阅和一个额外的变量来跟踪旧的(您可能已经尝试过):
var myObs = ko.observable(1);
// Keep track of old
var myObsOld = myObs();
myObs.subscribe(function(oldVal) {
myObsOld = oldVal;
}, null, "beforeChange");
// Subscribe to new
myObs.subscribe(function(newVal) {
console.log("myObs changed from", myObsOld, "to", newVal);
});
myObs(2);
myObs(3);
.as-console-wrapper { min-height: 100%; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
现在,如果您不想在视图模型中乱放额外的变量和订阅,您可以将此逻辑封装在扩展程序中:
ko.extenders.latestValue = function(target, option) {
target.latestValue = target();
target.subscribe(function(oldVal) {
target.latestValue = oldVal;
}, null, "beforeChange");
return target;
};
var myObs2 = ko.observable("a").extend({ latestValue: true });
myObs2.subscribe(function(newVal) {
console.log("myObs2 changed from", myObs2.latestValue, "to", newVal);
});
myObs2("b");
myObs2("c");
.as-console-wrapper { min-height: 100%; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
这不是一个非常性感的方法,但我认为它比分叉回购更好 :)
注意:此答案基于您对问题的评论而非原始问题。
当一个 observable 发生变化时,它会在该 observable 上调用一个名为 notifySubscribers
的方法,该方法会执行实际的通知,从而更新依赖于该 observable 的任何计算的 observable、绑定等。如果您想在任何这些通知之前执行某些操作,您有几种选择。
如@user3297291 所述,使用 Ryan Niemeyer 的 protectedObservable。
立即订阅可观察对象,然后再进行任何其他订阅。始终按顺序调用订阅者,因此您的代码将始终 运行 优先于其他任何内容。
Override
notifySubscribers
hook into the notification process (记得调用之前的方法)可能对于 Knockout 3.5.0,在
change
事件之前会有 aspectate
event。
这并不完全是对您请求的回应,但可能对略有不同的用例有用。
如果您不坚持在更改传播到可观察对象之前调用订阅并与 beforeChange 订阅一起触发,则可以创建自己的订阅,将旧值和新值一起推送到回调。
此订阅在更改发生后触发,它只是同时提供以前和当前的值。
/**
* extended version of knockout subscription provides to callback function new and previous value at once
* function Callback(newValue, originalValue) {...}
*
* @param {Function} callback function called on observable change
* @param {Object} context of the callback
* @return {Object} instance of changed subscription
*/
ko.subscribable.fn.subscribeChanged = function (callback, context) {
var savedValue = this.peek();
return this.subscribe(function (latestValue) {
var oldValue = savedValue;
savedValue = latestValue;
callback(latestValue, oldValue);
}, context);
};