KnockoutJS правильный способ обновления observableArray AJAX

Каков правильный способ обновления наблюдаемого массива данных JSON в KnockoutJS при каждом запуске команды AJAX?

Прямо сейчас я очищаю массив, используя что-то вроде viewmodel.items([]), а затем повторно заполняю его данными JSON с сервера. Если не считать использования подключаемого модуля сопоставления KnockoutJS (что может быть единственным способом сделать это), каков правильный путь?

Логика моего сервера будет каждый раз отправлять одни и те же данные, поэтому я не могу просто повторять и помещать элементы в массив, если мне не нужны дубликаты.

//// Добавляю, как я это делаю сегодня ////

Я не уверен, почему я делаю это именно так, но именно так я изначально понял, как обновлять. Итак, в основном, как я уже говорил, я получаю данные JSON, а затем передаю их примерно так:

    _model.addIncident = function (json) {
       var checked = json.UserTouches > 0 ? true : false;
       _model.incidents.push({
          id: ko.observable(json.IncidentIDString),
          lastTouchId: ko.observable(json.UserLastTouchIDString),
          weight: ko.observable(json.Weight),
          title: ko.observable(json.Title),
          checked: ko.observable(checked),
          createdOn: ko.observable(json.IncidentCreatedOn),
          servicename: ko.observable(json.Servicename),
          inEdit: ko.observable(false),
          incidentHistory: ko.observableArray(),
          matchScore: ko.observable()
      });
   };

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


person farina    schedule 19.03.2012    source источник


Ответы (2)


На самом деле observableArray — это обычный наблюдаемый объект с некоторыми дополнительными методами для операций с массивами.

Итак, если вы хотите установить значение observableArray в новый массив, вы можете просто сделать:

viewModel.items(myNewArray)

Плагин сопоставления может помочь вам обновить существующие элементы в массиве любыми обновлениями. В этом случае ваш UI будет обновляться только от каких-либо отличий.

person RP Niemeyer    schedule 19.03.2012
comment
Итак, я добавил пример того, что я сейчас делаю выше. В основном я создаю собственный массив для каждого элемента в моем JSON. Если бы я сделал это, а затем последовал вашему совету и закачал новый массив непосредственно в наблюдаемый, будет ли Knockout просто знать, что нужно игнорировать дубликаты? Может быть, это плохая структура? Спасибо за быстрый ответ... Мне не терпится узнать, как вы справляетесь с подобными обновлениями. Я пролистал сайт Knockout и никогда не видел простого решения для этого ... но это, вероятно, только моя вина :) - person farina; 19.03.2012
comment
Если вы используете привязку foreach (или template с параметром foreach), то пользовательский интерфейс будет обновляться соответствующим образом. Он будет правильно обрабатывать дубликаты, но имейте в виду, что старый элемент { name: 'Bob' } не равен новому элементу { name: 'Bob' }, если только они не являются ссылкой на один и тот же элемент. Именно здесь полезен плагин сопоставления вместе с его key функциональностью для получения обновленных данных и применения их к существующим объектам. Плагин картирования упрощает эту задачу. Судя по тому, что вы делаете выше, плагин сопоставления, вероятно, будет для вас хорошим выбором. - person RP Niemeyer; 19.03.2012
comment
Единственная проблема, которую я вижу с плагином отображения, заключается в том, что он сносит всю мою текущую модель представления вместо динамически созданной. Можете ли вы использовать плагин сопоставления для сопоставления данных JSON с наблюдаемым массивом внутри моей существующей модели? Я изучаю плагин для сопоставления, я думаю, вы правы, это похоже на способ двигаться вперед, просто я еще не знаком с ним. - person farina; 20.03.2012
comment
Я предполагаю, что более логичным примером был бы сценарий, в котором у меня есть функция пользовательского интерфейса в моей ViewModel... что-то вроде viewModel.somethingClicked = function(){}. Очевидно, я разместил это здесь, чтобы воспользоваться преимуществами привязки кликов шаблона, но, насколько я понимаю, плагин сопоставления потребует, чтобы я переместил эту логику за пределы нокаута, поскольку она не является частью моей модели данных JSON. - person farina; 20.03.2012
comment
Вы можете использовать плагин сопоставления, чтобы обновить часть вашей модели представления. Что-то вроде: ko.mapping.fromJSON(newArrayAsJson, null, viewModel.items). Вы должны использовать это против массива, который вы инициализировали с помощью плагина отображения, например: viewModel.items = ko.mapping.fromJS([]); - person RP Niemeyer; 20.03.2012
comment
Потрясающий! Я собираюсь попробовать это. Я отмечу это как ответ :). - person farina; 20.03.2012
comment
РП, если у вас есть возможность, не могли бы вы взглянуть на stackoverflow.com/questions/9774953/. Это связано с этой проблемой, и это очень странно. - person farina; 20.03.2012

Я знаю, что слишком опоздал с этим, так как совсем недавно застрял в этой ситуации. Мы можем использовать простую функцию Javascript в качестве обходного пути.

Если вы уже пометили _model.incidents как observableArray, вы можете сделать что-то подобное при привязке возвращаемых данных JSON:

eval("_model.incidents("+JSON.stringify(json)+");");

Это сработало для меня. Надеюсь, вы создали свою наблюдаемую следующим образом:

_model.incidents = ko.observableArray([]);
person Venkat    schedule 20.06.2013
comment
Проголосовали за зависимость от eval. Это похоже на какое-то странное вуду. Почему бы просто не _model.incidents(json); ? - person Luke H; 11.08.2015