Knockout Mapping для автоматического связывания

Knockout.js предоставляет мощный инструмент для работы с двусторонним связыванием данных через observables. Одной из ключевых библиотек для автоматизации процесса связывания является Knockout Mapping, позволяющая преобразовывать обычные JavaScript-объекты в observables и обратно без необходимости ручного объявления каждого свойства.


Подключение Knockout Mapping

Для использования Knockout Mapping требуется подключить основной Knockout.js и расширение mapping:

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

После этого доступны глобальные методы ko.mapping.fromJS и ko.mapping.toJS.


Преобразование объектов в observables

Метод ko.mapping.fromJS позволяет автоматически преобразовать обычный объект в объект, где все свойства являются observables:

var data = {
    name: "Иван",
    age: 30,
    address: {
        city: "Москва",
        street: "Тверская"
    }
};

var viewModel = ko.mapping.fromJS(data);

console.log(viewModel.name()); // Иван
console.log(viewModel.address.city()); // Москва

Особенности:

  • Вложенные объекты также автоматически преобразуются в observables.
  • Массивы превращаются в observableArray, позволяя отслеживать изменения элементов и их добавление/удаление.

Настройка отображения через mapping options

Knockout Mapping поддерживает настройку отображения через объект mapping, где можно задать правила для отдельных свойств:

var mapping = {
    'age': {
        create: function(options) {
            return ko.observable(options.data + 5); // увеличиваем возраст на 5 лет
        }
    },
    'address': {
        update: function(options) {
            return ko.observable(options.data.city.toUpperCase());
        }
    }
};

var viewModel = ko.mapping.fromJS(data, mapping);
console.log(viewModel.age()); // 35
console.log(viewModel.address()); // МОСКВА

Ключевые моменты:

  • create — вызывается при создании нового observable.
  • update — вызывается при обновлении существующего observable.
  • key — позволяет задать уникальный идентификатор для элементов массива.

Преобразование observables обратно в обычные объекты

Метод ko.mapping.toJS используется для преобразования observables обратно в обычные объекты:

var plainData = ko.mapping.toJS(viewModel);
console.log(plainData);
// {
//     name: "Иван",
//     age: 35,
//     address: "МОСКВА"
// }

Также существует метод ko.mapping.toJSON, который сразу возвращает JSON-строку:

var jsonData = ko.mapping.toJSON(viewModel);
console.log(jsonData);
// {"name":"Иван","age":35,"address":"МОСКВА"}

Работа с массивами

Knockout Mapping особенно полезен для массивов объектов:

var data = [
    { name: "Иван", age: 30 },
    { name: "Мария", age: 25 }
];

var viewModel = ko.mapping.fromJS(data);

viewModel.push({ name: "Алексей", age: 40 });

console.log(viewModel()[2].name()); // Алексей

Особенности работы с массивами:

  • Методы массива (push, pop, splice) полностью совместимы с observableArray.
  • Можно использовать опции key, чтобы корректно обновлять массив при получении новых данных с сервера.

Пример сложной настройки для массивов

var mapping = {
    'items': {
        key: function(data) {
            return ko.utils.unwrapObservable(data.id);
        },
        create: function(options) {
            return new ItemModel(options.data);
        }
    }
};

function ItemModel(data) {
    this.id = ko.observable(data.id);
    this.name = ko.observable(data.name);
}

Такой подход позволяет:

  • Обновлять существующие элементы массива без их полного пересоздания.
  • Создавать собственные модели для каждого элемента массива с дополнительной логикой.

Рекомендации по использованию

  • Использовать ko.mapping.fromJS для инициализации ViewModel при получении данных с сервера.
  • Применять mapping options для контроля преобразований и создания кастомных observable.
  • Для больших массивов использовать key, чтобы избежать пересоздания элементов и сохранить состояние.
  • Для отправки данных на сервер применять ko.mapping.toJS или ko.mapping.toJSON для получения чистого объекта или JSON.

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