Knockout.js — это JavaScript-фреймворк, реализующий паттерн Model-View-ViewModel (MVVM). Основная сила Knockout заключается в его способности создавать реактивные связи между моделью данных и пользовательским интерфейсом, что позволяет автоматически обновлять представление при изменении состояния модели без явного вмешательства в DOM.
В основе реактивной системы Knockout лежит объект observable. Observable представляет собой специальный контейнер для значения, который уведомляет подписчиков об изменениях.
Пример объявления observable:
var firstName = ko.observable("Иван");
Для получения значения используется вызов как функции:
console.log(firstName()); // "Иван"
Для изменения значения:
firstName("Алексей");
console.log(firstName()); // "Алексей"
Каждое изменение автоматически оповещает все подписки (bindings), связанные с этим observable, что и обеспечивает реактивное поведение.
Для работы с массивами существует специальный тип — observableArray, который позволяет не только отслеживать изменения элементов, но и управлять ими через методы массивов:
var items = ko.observableArray(["яблоко", "банан"]);
items.push("груша");
items.remove("банан");
Изменения observableArray автоматически отражаются в интерфейсе, если элементы связаны через bindings.
Computed observable позволяет создавать вычисляемые значения, которые зависят от других observables. Это аналог реактивных вычислений:
var firstName = ko.observable("Иван");
var lastName = ko.observable("Иванов");
var fullName = ko.computed(function() {
return firstName() + " " + lastName();
});
console.log(fullName()); // "Иван Иванов"
firstName("Алексей");
console.log(fullName()); // "Алексей Иванов"
Computed автоматически подписывается на все observables, используемые внутри функции, и обновляется при их изменении.
Knockout.js обеспечивает реактивное обновление DOM через bindings. Самый простой пример — связывание текста с observable:
<p data-bind="text: firstName"></p>
При изменении firstName содержимое
<p> обновится автоматически. Основные типы
bindings:
Bindings обеспечивают реактивное взаимодействие модели и представления без необходимости вручную манипулировать DOM.
Observable предоставляет возможность явно подписываться на изменения:
firstName.subscribe(function(newValue) {
console.log("Имя изменилось на " + newValue);
});
Subscriptions полезны для выполнения дополнительных действий при изменении состояния модели, например, валидации данных или вызова внешних API.
function PersonViewModel() {
this.firstName = ko.observable("Иван");
this.lastName = ko.observable("Иванов");
this.age = ko.observable(30);
this.fullName = ko.computed(() => this.firstName() + " " + this.lastName());
this.increaseAge = () => {
this.age(this.age() + 1);
};
}
var vm = new PersonViewModel();
ko.applyBindings(vm);
<p data-bind="text: fullName"></p>
<p>Возраст: <span data-bind="text: age"></span></p>
<button data-bind="click: increaseAge">Увеличить возраст</button>
При нажатии на кнопку возраст увеличивается, а полное имя обновляется автоматически, если изменить имя или фамилию. Вся реактивность реализована через observables и computed, без прямых манипуляций с DOM.
Реактивность в Knockout.js строится на наблюдаемых значениях, вычисляемых свойствах и bindings, которые связывают модель и представление. Такая архитектура снижает необходимость ручного управления DOM и позволяет строить динамичные интерфейсы с минимальными затратами кода и ошибок синхронизации.