Knockout.js предоставляет мощный механизм для реактивного обновления интерфейса через observables. Помимо обычных observables, фреймворк предлагает computed observables, которые позволяют создавать значения, автоматически зависящие от других observables и обновляющиеся при их изменении.
Computed observable — это функция, результат которой зависит от одного или нескольких observables. Она вычисляется автоматически и кэшируется, обновляясь только при изменении зависимых значений.
Пример базового computed:
var firstName = ko.observable("Иван");
var lastName = ko.observable("Петров");
var fullName = ko.computed(function() {
return firstName() + " " + lastName();
});
console.log(fullName()); // "Иван Петров"
firstName("Алексей");
console.log(fullName()); // "Алексей Петров"
Ключевые моменты:
ko.computed принимает функцию, которая возвращает
значение.Computed observables отслеживают любые observables, к которым происходит обращение через вызов функции. Этот механизм делает их мощным инструментом для создания реактивных связей в данных.
Пример с несколькими зависимостями:
var price = ko.observable(100);
var quantity = ko.observable(2);
var total = ko.computed(function() {
return price() * quantity();
});
console.log(total()); // 200
price(150);
console.log(total()); // 300
Здесь computed total зависит сразу от двух observables:
price и quantity.
Computed observables поддерживают объект конфигурации с полезными параметрами:
this для функций
read/write.true,
вычисление откладывается до первого обращения к computed.Пример с write:
var celsius = ko.observable(25);
var fahrenheit = ko.computed({
read: function() {
return celsius() * 9 / 5 + 32;
},
write: function(value) {
celsius((value - 32) * 5 / 9);
}
});
fahrenheit(212);
console.log(celsius()); // 100
console.log(fahrenheit()); // 212
Computed observables кэшируют значение, пересчитываясь только при изменении зависимостей. Это предотвращает лишние вычисления и улучшает производительность, особенно в сложных интерфейсах.
Если computed зависит от больших массивов или дорогих вычислений, можно использовать pure computed, которая оптимизирована для минимизации лишних обновлений:
var numbers = ko.observableArray([1, 2, 3]);
var sum = ko.pureComputed(function() {
return numbers().reduce((a, b) => a + b, 0);
});
console.log(sum()); // 6
numbers.push(4);
console.log(sum()); // 10
Особенности pure computed:
Computed можно использовать как обычные observables для подписки на изменения:
var firstName = ko.observable("Иван");
var lastName = ko.observable("Петров");
var fullName = ko.computed(function() {
return firstName() + " " + lastName();
});
fullName.subscribe(function(newValue) {
console.log("Новое полное имя: " + newValue);
});
firstName("Алексей"); // "Новое полное имя: Алексей Петров"
Подписки позволяют интегрировать вычисляемые значения с другими частями приложения, например, для обновления данных на сервере или запуска анимаций.
Computed observables могут использоваться внутри других computed, создавая цепочку реактивных зависимостей:
var a = ko.observable(2);
var b = ko.observable(3);
var sum = ko.computed(() => a() + b());
var doubleSum = ko.computed(() => sum() * 2);
console.log(doubleSum()); // 10
a(4);
console.log(doubleSum()); // 14
Knockout автоматически отслеживает все зависимости, поэтому любые
изменения a или b корректно обновят
sum и doubleSum.
Computed observables можно явно уничтожать для освобождения памяти, особенно при динамически создаваемых компонентах:
var temp = ko.computed(() => Math.random());
temp.dispose();
После вызова dispose computed больше не будет
пересчитываться и освобождает все подписки на observables.
Computed observables превращают Knockout.js в мощный инструмент для реактивного программирования, позволяя строить динамические интерфейсы с минимальной нагрузкой на код и оптимизированной производительностью.