Open mbest opened 8 years ago
Analyzing the knockout
code, this appears to be because the wrapper methods for ko.observableArray
do not go through the normal update path for a ko.observable
. The issue is this passage:
ko.utils.arrayForEach(["pop", "push", "reverse", "shift", "sort", "splice", "unshift"], function (methodName) {
ko.observableArray['fn'][methodName] = function () {
// Use "peek" to avoid creating a subscription in any computed that we're executing in the context of
// (for consistency with mutating regular observables)
var underlyingArray = this.peek();
this.valueWillMutate();
this.cacheDiffForKnownOperation(underlyingArray, methodName, arguments);
var methodCallResult = underlyingArray[methodName].apply(underlyingArray, arguments);
this.valueHasMutated();
// The native sort and reverse methods return a reference to the array, but it makes more sense to return the observable array instead.
return methodCallResult === underlyingArray ? this : methodCallResult;
};
});
Here, when you use the wrapper method, it simply goes updates the underlying array directly, in between calls to this.valueWillMutate()
and this.valueHasMutated()
, bypassing the normal diff call from ko.observable
. I would assume the bugfix would be to add a conditional around this.valueHasMutated()
which checks a call to this.equalityComparer
first.
I don't think there's anything an equalityComparer could do with an array. Once the array is updated, the old version of the array is gone. As I mentioned in the forum, we have the arrayChange
event which notifies only actual changes in the array.
I meant for this issue to note that we might want to not call equalityComparer
at all for arrays, because currently it's called only sometimes.
from https://groups.google.com/d/msg/knockoutjs/2lj89SXHGJ8/V5CnEFDuCgAJ