什么时候调用 Knockout 的 ObservableArray 订阅
When is Knockout's ObservableArray subscribe called
只有当值发生变化时,才应调用任何 knockout obervable 的 subscribe()
。但是在下面的代码片段中,即使将相同的值分配给可观察对象两次,也会调用订阅。我可以理解一旦 subscribe 将被调用(即当第一次 x 被赋予 y 的值时)但我不明白的是为什么它第二次被调用,当赋值没有变化时?有人可以帮我了解订阅的工作原理吗?
// This is a simple *viewmodel* - JavaScript that defines the data and behavior of your UI
function AppViewModel() {
var x = ko.observableArray([]);
var y = [1];
var oldVal = '';
x.subscribe(function(newVal){
alert("newVal: "+newVal+" oldVal: "+oldVal);
console.log("newVal: "+newVal+" oldVal: "+oldVal);
var type = newVal instanceof Array;
alert(type);
oldVal = newVal;
});
x(y);
x(y);
}
// Activates knockout.js
ko.applyBindings(new AppViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
Any knockout obervable's subscribe() should be called only when there is a change in the value.
根据淘汰维护者的说法,这并不完全正确。
Knockout 使用 equalityComparer
来确定新值是否与旧值不同:
console.log(
ko.observable.fn.equalityComparer
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-debug.js"></script>
如您所见,如果值是原始值,它实际上只会执行 ===
。任何其他值,如对象、数组和函数,只是 总是 触发更改。
我通常 "fix" 通过覆盖默认值:
const someObj = {};
const someObs = ko.observable(someObj);
someObs.subscribe(console.log);
// Logs {}
console.log("with regular eq comparer");
someObs(someObj);
// Change equalityComparer for *every* observable:
ko.observable.fn.equalityComparer = (a, b) => a === b;
// No longer logs:
console.log("with custom eq comparer");
someObs(someObj);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
如果你不想覆盖所有的 equalityComparer,你也可以只在一个可观察的实例上改变它。
默认行为的原因是许多人希望这会触发更新:(当您使用我的自定义比较器时它不会)
const someObj = { a: 1 };
const someObs = ko.observable(someObj);
someObj.a = 2;
someObs(someObj)
只有当值发生变化时,才应调用任何 knockout obervable 的 subscribe()
。但是在下面的代码片段中,即使将相同的值分配给可观察对象两次,也会调用订阅。我可以理解一旦 subscribe 将被调用(即当第一次 x 被赋予 y 的值时)但我不明白的是为什么它第二次被调用,当赋值没有变化时?有人可以帮我了解订阅的工作原理吗?
// This is a simple *viewmodel* - JavaScript that defines the data and behavior of your UI
function AppViewModel() {
var x = ko.observableArray([]);
var y = [1];
var oldVal = '';
x.subscribe(function(newVal){
alert("newVal: "+newVal+" oldVal: "+oldVal);
console.log("newVal: "+newVal+" oldVal: "+oldVal);
var type = newVal instanceof Array;
alert(type);
oldVal = newVal;
});
x(y);
x(y);
}
// Activates knockout.js
ko.applyBindings(new AppViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
Any knockout obervable's subscribe() should be called only when there is a change in the value.
根据淘汰维护者的说法,这并不完全正确。
Knockout 使用 equalityComparer
来确定新值是否与旧值不同:
console.log(
ko.observable.fn.equalityComparer
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-debug.js"></script>
如您所见,如果值是原始值,它实际上只会执行 ===
。任何其他值,如对象、数组和函数,只是 总是 触发更改。
我通常 "fix" 通过覆盖默认值:
const someObj = {};
const someObs = ko.observable(someObj);
someObs.subscribe(console.log);
// Logs {}
console.log("with regular eq comparer");
someObs(someObj);
// Change equalityComparer for *every* observable:
ko.observable.fn.equalityComparer = (a, b) => a === b;
// No longer logs:
console.log("with custom eq comparer");
someObs(someObj);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
如果你不想覆盖所有的 equalityComparer,你也可以只在一个可观察的实例上改变它。
默认行为的原因是许多人希望这会触发更新:(当您使用我的自定义比较器时它不会)
const someObj = { a: 1 };
const someObs = ko.observable(someObj);
someObj.a = 2;
someObs(someObj)