Knockout.js — это легковесный JavaScript-фреймворк, обеспечивающий
двустороннее связывание данных (two-way data binding) между моделью и
представлением. Основная идея заключается в том, что модель данных
управляет состоянием интерфейса, а представление автоматически
обновляется при изменении модели. В отличие от jQuery, где управление
DOM осуществляется вручную через методы вроде .append(),
.html(), .on(), Knockout.js использует
декларативные привязки (bindings), что упрощает поддержку и тестирование
кода.
Ключевые элементы:
data-bind="text: propertyName" или
data-bind="foreach: items".В jQuery часто встречаются следующие сценарии:
$('#itemCount').text(items.length);
$('#addItem').on('click', function() {
items.push('новый элемент');
});
В Knockout.js это решается с помощью observables и привязок:
function ViewModel() {
this.items = ko.observableArray([]);
this.addItem = function() {
this.items.push('новый элемент');
}.bind(this);
}
ko.applyBindings(new ViewModel());
HTML:
<div data-bind="text: items().length" id="itemCount"></div>
<button data-bind="click: addItem" id="addItem">Добавить элемент</button>
Преимущество подхода в том, что больше не требуется вручную искать элементы и обновлять их. Изменение модели автоматически отражается на интерфейсе.
jQuery использует методы .on() и .click()
для подписки на события. Knockout.js предлагает директиву
click, а также другие bindings (event,
submit, value для форм). Например:
jQuery:
$('#inputField').on('input', function() {
$('#output').text($(this).val());
});
Knockout.js:
function ViewModel() {
this.inputValue = ko.observable('');
}
ko.applyBindings(new ViewModel());
HTML:
<input data-bind="value: inputValue, valueUpdate: 'input'" />
<div data-bind="text: inputValue"></div>
Директива valueUpdate: 'input' позволяет отслеживать
изменения в реальном времени, аналогично обработчику input
в jQuery.
В jQuery добавление элементов требует явного создания HTML и вставки в DOM:
items.forEach(function(item) {
$('#list').append('<li>' + item + '</li>');
});
В Knockout.js используется binding foreach:
function ViewModel() {
this.items = ko.observableArray(['Элемент 1', 'Элемент 2']);
}
ko.applyBindings(new ViewModel());
HTML:
<ul data-bind="foreach: items">
<li data-bind="text: $data"></li>
</ul>
Изменения в items автоматически обновляют список. Это
устраняет необходимость вручную манипулировать DOM и предотвращает
ошибки при обновлении интерфейса.
В jQuery условное отображение обычно делается через
.show(), .hide() или
.toggleClass():
if(isVisible) {
$('#panel').show();
} else {
$('#panel').hide();
}
В Knockout.js применяется binding visible и
css:
function ViewModel() {
this.isVisible = ko.observable(true);
}
ko.applyBindings(new ViewModel());
HTML:
<div data-bind="visible: isVisible">Панель</div>
<div data-bind="css: { 'highlight': isVisible }">Подсветка</div>
Любые изменения состояния isVisible автоматически
обновляют видимость и CSS-класс.
jQuery-код часто представляет собой последовательность скриптов, зависящих от состояния DOM. Knockout.js способствует модульной архитектуре через ViewModel и вычисляемые свойства. В сложных приложениях можно разделять ViewModel на подмодули и связывать их через observables:
function Item(name, quantity) {
this.name = ko.observable(name);
this.quantity = ko.observable(quantity);
}
function CartViewModel() {
this.items = ko.observableArray([
new Item('Яблоко', 3),
new Item('Апельсин', 5)
]);
this.totalQuantity = ko.computed(function() {
return this.items().reduce((sum, item) => sum + item.quantity(), 0);
}, this);
}
ko.applyBindings(new CartViewModel());
HTML:
<ul data-bind="foreach: items">
<li>
<span data-bind="text: name"></span> -
<span data-bind="text: quantity"></span>
</li>
</ul>
<p>Всего товаров: <span data-bind="text: totalQuantity"></span></p>
.html(), .append(), .text()
заменяется соответствующим binding.Такой подход позволяет плавно перейти от императивного управления DOM к декларативному, снижает количество багов и упрощает поддержку интерфейса.