Я уже давно пытаюсь понять это. Я не смог найти ничего, что решило бы эту проблему, но, пожалуйста, поправьте меня, если я ошибаюсь.
Проблема:
У меня есть данные от JSON API, входящего, с вложенной структурой массива / объекта. Я использую отображение, чтобы изначально заполнить модель моими данными. Чтобы обновить это, я хочу расширить модель, если поступают новые данные, или обновить существующие данные.
Насколько я выяснил, ключ опции сопоставления должен сделать для меня этот трюк, но я мог неправильно понять функциональность параметров сопоставления.
Я выполнил задачу, которая будет представлена в этом примере:
var userMapping = {
key: function(item) {
return ko.utils.unwrapObservable(item.id);
}
};
// JSON call replaced with values
var viewModel = {
users: ko.mapping.fromJS([], userMapping)
};
// Should insert new - new ID?
ko.mapping.fromJS([{"id":1,"name":"Foo"}, {"id":2,"name":"Bar"}], userMapping, viewModel.users);
// Should only update ID#1 - same ID?
ko.mapping.fromJS([{"id":1,"name":"Bat"}], userMapping, viewModel.users);
// Should insert new - New ID?
ko.mapping.fromJS([{"id":3,"name":"New"}, {"id":4,"name":"New"}], userMapping, viewModel.users);
ko.applyBindings(viewModel);
Скрипка: http://jsfiddle.net/mikaelbr/gDjA7/
Как видите, первая строка вставляет данные. Все хорошо. Но когда я пытаюсь обновить, он заменяет контент. То же самое для третьего отображения; он заменяет контент, а не расширяет его.
Я использую это неправильно? Стоит ли пытаться расширить содержимое «вручную» перед использованием сопоставления?
Редактировать решение:
Я решил этот случай, имея второй вспомогательный массив, хранящий все текущие модели. На новых данных я расширил этот массив и обновил модель представления, чтобы содержать накопленные элементы.
При обновлении (в моем случае сообщение WebSocket) я просматривал модели, изменял содержимое рассматриваемого элемента и использовал метод valueHasMutated (), чтобы уведомить об измененном значении в библиотеке Knockout.