KnockoutJS - wyliczone obserwowalne
Obliczane obserwowalne to funkcja, która jest zależna od jednego lub więcej Observables i automatycznie aktualizuje się, gdy zmieniają się jej podstawowe Observables (zależności).
Obliczone obserwacje można łączyć w łańcuchy.
Składnia
this.varName = ko.computed(function(){
...
... // function code
...
},this);
Przykład
Spójrzmy na poniższy przykład, który demonstruje użycie wyliczonych obserwowalnych.
<!DOCTYPE html>
<head >
<title>KnockoutJS Computed Observables</title>
<script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.1.0.js"></script>
</head>
<body>
<p>Enter first number: <input data-bind = "value: a" /></p>
<p>Enter second number: <input data-bind = "value: b"/></p>
<p>Average := <span data-bind="text: totalAvg"></span></p>
<script>
function MyViewModel() {
this.a = ko.observable(10);
this.b = ko.observable(40);
this.totalAvg = ko.computed(function() {
if(typeof(this.a()) !== "number" || typeof(this.b()) !== "number") {
this.a(Number(this.a())); //convert string to Number
this.b(Number(this.b())); //convert string to Number
}
total = (this.a() + this.b())/2 ;
return total;
},this);
}
ko.applyBindings(new MyViewModel());
</script>
</body>
</html>
W kolejnych wierszach pierwsze dwa służą do akceptowania wartości wejściowych. Trzecia linia wypisuje średnią z tych dwóch liczb.
<p>Enter first number: <input data-bind = "value: a" /></p>
<p>Enter second number: <input data-bind = "value: b"/></p>
<p>Average := <span data-bind = "text: totalAvg"></span></p>
W kolejnych wierszach wpisz Observables a i bto liczba, gdy są inicjowane po raz pierwszy w ViewModel. Jednak w KO każde wejście akceptowane z UI jest domyślnie w formacie String. Dlatego należy je przekonwertować na liczbę, aby wykonać na nich operacje arytmetyczne.
this.totalAvg = ko.computed(function() {
if(typeof(this.a()) !== "number" || typeof(this.b()) !== "number") {
this.a(Number(this.a())); //convert string to Number
this.b(Number(this.b())); //convert string to Number
}
total = (this.a() + this.b())/2 ;
return total;
},this);
W następnym wierszu obliczona średnia jest wyświetlana w interfejsie użytkownika. Zauważ, że typ wiązania danych totalAvg to tylko tekst.
<p>Average := <span data-bind = "text: totalAvg"></span></p>
Wynik
Wykonajmy następujące kroki, aby zobaczyć, jak działa powyższy kod -
Zapisz powyższy kod w formacie computed-observable.htm plik.
Otwórz ten plik HTML w przeglądarce.
Wprowadź dowolne 2 liczby w pola tekstowe i obserwuj, jak obliczana jest średnia.
Zarządzanie tym
Zauważ, że w powyższym przykładzie drugi parametr jest podany jako thisdo funkcji obliczonej. Nie ma możliwości odniesienia się do Observablesa() i b() bez podania this.
Aby to przezwyciężyć, self używana jest zmienna, która przechowuje odniesienie do this. W ten sposób nie ma potrzeby śledzeniathisw całym kodzie. Zamiast,self może być zastosowane.
Poniższy kod ViewModel jest przepisywany dla powyższego przykładu przy użyciu self.
function MyViewModel(){
self = this;
self.a = ko.observable(10);
self.b = ko.observable(40);
this.totalAvg = ko.computed(function() {
if(typeof(self.a()) !== "number" || typeof(self.b()) !== "number") {
self.a(Number(self.a())); //convert string to Number
self.b(Number(self.b())); //convert string to Number
}
total = (self.a() + self.b())/2 ;
return total;
});
}
Czyste wyliczone obserwowalne
Wyliczony obserwowalny powinien być zadeklarowany jako PureObliczone obserwowalne, jeśli to obserwowalne po prostu oblicza i zwraca wartość, a nie bezpośrednio modyfikuje inne obiekty lub stan. Pure Computed Observables pomaga Knockout w efektywnym zarządzaniu ponownymi ocenami i zużyciem pamięci.
Jawne powiadamianie subskrybentów
Kiedy wyliczana obserwowalna zwraca wartość pierwotnego typu danych (String, Boolean, Null i Number), wówczas jej subskrybenci są powiadamiani wtedy i tylko wtedy, gdy ma miejsce rzeczywista zmiana wartości. Oznacza to, że jeśli Observable otrzymał taką samą wartość jak poprzednia wartość, to jego subskrybenci nie są powiadamiani.
Można sprawić, że wyliczone obserwacje zawsze będą jawnie powiadamiać obserwatorów, nawet jeśli nowa wartość jest taka sama jak stara, używając funkcji notify składnia w następujący sposób.
myViewModel.property = ko.pureComputed(function() {
return ...; // code logic goes here
}).extend({ notify: 'always' });
Ograniczanie powiadomień o zmianach
Zbyt wiele kosztownych aktualizacji może spowodować problemy z wydajnością. Możesz ograniczyć liczbę powiadomień otrzymywanych od Observable za pomocąrateLimit atrybut w następujący sposób.
// make sure there are updates no more than once per 100-millisecond period
myViewModel.property.extend({ rateLimit: 100 });
Sprawdzanie, czy właściwość jest obliczana i obserwowalna
W pewnych sytuacjach może być konieczne ustalenie, czy właściwość jest obserwowalną wyliczaną. Do identyfikacji typów Observables można użyć następujących funkcji.
Sr.No. | Funkcjonować |
---|---|
1 | ko.isComputed Zwroty true jeśli właściwość jest obserwowalna wyliczana. |
2 | ko.isObservable Zwroty true jeśli właściwość to Observable, Observable array lub Computed Observable. |
3 | ko.isWritableObservable Zwroty trueif Observable, Observable array lub Writable Computed Observable. (Nazywa się to również jako ko.isWriteableObservable) |
Zapisywalne wyliczane obserwowalne
Obliczona obserwowalna pochodzi z jednego lub wielu innych Observables, więc jest tylko do odczytu. Jednak jest możliwe, że można sprawić, że wyliczany obserwowalny będzie zapisywalny. W tym celu musisz zapewnić funkcję zwrotną, która działa na zapisanych wartościach.
Te zapisywalne wyliczane obserwowalne działają tak samo jak zwykłe obserwowalne. Ponadto wymagają zbudowania niestandardowej logiki w celu zakłócania operacji odczytu i zapisu.
Można przypisać wartości do wielu właściwości Observables lub Computed Observable, używając składni łańcuchowej w następujący sposób.
myViewModel.fullName('Tom Smith').age(45)
Przykład
Poniższy przykład demonstruje użycie Writable Computable Observable.
<!DOCTYPE html>
<head >
<title>KnockoutJS Writable Computed Observable</title>
<script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.3.0.js"></script>
</head>
<body>
<p>Enter your birth Date: <input type = "date" data-bind = "value: rawDate" ></p>
<p><span data-bind = "text: yourAge"></span></p>
<script>
function MyViewModel() {
this.yourAge = ko.observable();
today = new Date();
rawDate = ko.observable();
this.rawDate = ko.pureComputed ({
read: function() {
return this.yourAge;
},
write: function(value) {
var b = Date.parse(value); // convert birth date into milliseconds
var t = Date.parse(today); // convert todays date into milliseconds
diff = t - b; // take difference
var y = Math.floor(diff/31449600000); // difference is converted
// into years. 31449600000
//milliseconds form a year.
var m = Math.floor((diff % 31449600000)/604800000/4.3); // calculating
// months.
// 604800000
// milliseconds
// form a week.
this.yourAge("You are " + y + " year(s) " + m +" months old.");
},
owner: this
});
}
ko.applyBindings(new MyViewModel());
</script>
</body>
</html>
W powyższym kodzie rawDate to właściwość pureComputed akceptowana z interfejsu użytkownika. yourAge Observable pochodzi z rawDate.
Daty w JavaScript są przetwarzane w milisekundach. W związku z tym obie daty (dzisiejsza data i data urodzenia) są przeliczane na milisekundy, a następnie różnica między nimi jest przeliczana z powrotem na lata i miesiące.
Wynik
Wykonajmy następujące kroki, aby zobaczyć, jak działa powyższy kod -
Zapisz powyższy kod w formacie writable_computed_observable.htm plik.
Otwórz ten plik HTML w przeglądarce.
Wprowadź dowolną datę urodzenia i obserwuj, czy wiek jest obliczany.