Когда вызывается подписка на Knockout ObservableArray - PullRequest
0 голосов
/ 12 сентября 2018

Любой нокаутируемый obervable 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>

1 Ответ

0 голосов
/ 12 сентября 2018

Аргумент подписки любого нокаута obervable следует вызывать только при изменении значения.

Это не совсем так, согласно сопровождающим нокаута.

Knockout использует equalityComparer, чтобы определить, отличается ли новое значение от старого:

console.log(
  ko.observable.fn.equalityComparer
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-debug.js"></script>

Как видите, на самом деле он === только делает, если значения примитивны.Любые другие значения, такие как объекты, массивы и функции, просто всегда вызывают изменение.

Я обычно "исправляю" это, перезаписывая значение по умолчанию:

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>

Если вы не хотите перезаписывать все равенство равенства, вы также можете изменить его только на одном наблюдаемом экземпляре.

ПричиныПо умолчанию многие люди ожидают, что это вызовет обновления: (чего не происходит, когда вы используете мой пользовательский компаратор)

const someObj = { a: 1 };
const someObs = ko.observable(someObj);

someObj.a = 2;
someObs(someObj)
...