Первое приложение на Knockout.js

Knockout.js — это библиотека JavaScript для построения динамических интерфейсов с применением паттерна MVVM (Model-View-ViewModel). Она позволяет связывать данные с HTML-разметкой через декларативные привязки, автоматически обновляя представление при изменении модели данных.

Подключение Knockout.js

Для начала необходимо подключить библиотеку к проекту. Это можно сделать через CDN:

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.5.1/knockout-min.js"></script>

или локально, скачав библиотеку и подключив её через тег <script>.

Основные концепции

Observable — это базовый строительный блок Knockout. Это специальный объект, который хранит значение и уведомляет подписчиков при его изменении.

var firstName = ko.observable('Иван');
firstName('Алексей'); // изменение значения
console.log(firstName()); // получение текущего значения

Observable Array — массив, за которым Knockout следит, автоматически обновляя привязанные элементы при добавлении или удалении значений.

var items = ko.observableArray(['Яблоко', 'Банан']);
items.push('Апельсин');
items.remove('Банан');

Computed — вычисляемое значение, зависящее от других observables. Автоматически обновляется при изменении зависимостей.

var firstName = ko.observable('Иван');
var lastName = ko.observable('Петров');
var fullName = ko.computed(function() {
    return firstName() + ' ' + lastName();
});

Декларативные привязки

Knockout использует data-bind для связывания элементов HTML с моделью данных.

Примеры привязок:

  • text — вывод текста в элементе:
<span data-bind="text: firstName"></span>
  • value — привязка значения формы (input, select):
<input type="text" data-bind="value: firstName">
  • click — обработка событий клика:
<button data-bind="click: sayHello">Привет</button>
  • foreach — циклический вывод элементов массива:
<ul data-bind="foreach: items">
    <li data-bind="text: $data"></li>
</ul>

Создание ViewModel

ViewModel — объект, содержащий данные и логику приложения. Он является связующим звеном между моделью и представлением.

function AppViewModel() {
    this.firstName = ko.observable('Иван');
    this.lastName = ko.observable('Петров');

    this.fullName = ko.computed(() => {
        return this.firstName() + ' ' + this.lastName();
    });

    this.items = ko.observableArray(['Яблоко', 'Банан']);

    this.addItem = () => {
        this.items.push('Апельсин');
    };

    this.removeItem = (item) => {
        this.items.remove(item);
    };
}

ko.applyBindings(new AppViewModel());

Пример HTML-разметки для приложения

<div>
    <h2 data-bind="text: fullName"></h2>
    <input type="text" data-bind="value: firstName">
    <input type="text" data-bind="value: lastName">
    
    <ul data-bind="foreach: items">
        <li>
            <span data-bind="text: $data"></span>
            <button data-bind="click: $parent.removeItem">Удалить</button>
        </li>
    </ul>
    
    <button data-bind="click: addItem">Добавить Апельсин</button>
</div>

Динамическое обновление интерфейса

Любое изменение observable автоматически отражается в привязанной разметке:

viewModel.firstName('Сергей'); // Заголовок и input обновятся автоматически
viewModel.items.push('Груша'); // Список <ul> обновится автоматически

Подписки на изменения

Knockout позволяет выполнять действия при изменении observable через метод subscribe:

viewModel.firstName.subscribe(function(newValue) {
    console.log('Имя изменилось на: ' + newValue);
});

Дополнительные привязки и возможности

  • visible — управление видимостью элемента:
<div data-bind="visible: isVisible">Этот блок виден только если isVisible true</div>
  • enable / disable — включение или блокировка элементов управления.
  • options — привязка массива к элементу <select>.
  • template — использование шаблонов для сложного рендеринга.

Организация приложения

Для крупных приложений рекомендуется:

  • Разделять ViewModel на отдельные модули.
  • Использовать computed для вычисляемых свойств.
  • Применять observableArray для динамических списков.
  • Минимизировать прямое манипулирование DOM — полагаться на привязки Knockout.

Интеграция с AJAX

Knockout легко интегрируется с асинхронными запросами:

fetch('/api/items')
    .then(response => response.json())
    .then(data => {
        viewModel.items(data);
    });

observableArray автоматически обновит интерфейс после получения данных.

Реактивность и производительность

Knockout оптимизирует обновление DOM. Только изменившиеся элементы перерисовываются, что позволяет строить производительные интерфейсы без ручного контроля за состоянием.


Knockout.js обеспечивает простой, но мощный способ построения реактивных интерфейсов, позволяя отделить логику от представления и сделать код более структурированным и поддерживаемым.