Подтвердить что ты не робот

AngularJS: ng-repeat с динамическим списком, без восстановления всего дерева DOM?

Я использую ng-repeat в строке таблицы с данными из массива JSON, полученным с сервера. Моя цель - автоматически обновлять список всякий раз, когда элемент добавляется, удаляется или изменяется на сервере, не затрагивая неизмененные элементы. В финальной реализации эти строки таблицы также содержат привязанные к двунаправленным элементам <input> и <select> для отправки обновлений обратно на сервер. Некоторые из доступных опций в элементах <select> также будут сгенерированы с использованием директив ng-repeat из другого списка, который также может измениться.

До сих пор каждый раз, когда новый массив поступает с сервера (в настоящее время опрошено каждые две секунды), весь список ng-repeat удаляется и регенерируется. Это проблематично, поскольку оно мешает выбору текста, уничтожает поля ввода, даже если они в настоящее время редактируются пользователем, и, вероятно, работает намного медленнее, чем необходимо.

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

Итак, вот вопрос: можно ли обновить массив поддержки таким образом, но изменить только элементы DOM, соответствующие фактически изменяемым элементам/свойствам?


Здесь минимальный тестовый пример, который имитирует периодический опрос с использованием жестко закодированного массива в таймере (см. его в режиме http://jsfiddle.net/DWrmP/). Обратите внимание, что выбор текста очищается каждые 500 мс из-за стирания и воссоздания элементов.

HTML

<body ng-app="myApp">
    <table ng-controller="MyController">
        <tr ng-repeat="item in items | orderBy:'id'">
            <td>{{item.id}}</td>
            <td>{{item.data}}</td>
        </tr>
    </table>
</body>

JavaScript

angular.module('myApp', []).controller(
    'MyController', [
        '$scope', '$timeout',
        function($scope, $timeout) {
            $scope.items = [
                { id: 0, data: 'Zero' }
            ];

            function setData() {
                $scope.items = [
                    { id: 1, data: 'One' },
                    { id: 2, data: 'Two' },
                    { id: 5, data: 'Five' },
                    { id: 4, data: 'Four' },
                    { id: 3, data: 'Three' }
                    ];
                $timeout(setData, 500);
            }
            $timeout(setData, 500);
        }
        ]
);
4b9b3361

Ответ 1

Для тех, кто находит это в google, страница ниже описывает функцию в AngularJS 1.2, которая помогает с этой проблемой:

http://www.bennadel.com/blog/2556-Using-Track-By-With-ngRepeat-In-AngularJS-1-2.htm


Изменить добавление: самые важные предложения из связанного сообщения, если связь когда-либо умирает:

С новым синтаксисом "track by" я могу теперь сообщить AngularJS, какое свойство объекта (или путь свойства) следует использовать для связывания объекта JavaScript с DOM node. Это означает, что я могу поменять местами объекты JavaScript, не разрушая узлы DOM, пока ассоциация "track by" все еще работает.

Ответ 3

Я планирую самостоятельно создать следующее решение, хотя оно все еще находится в моем отставании продукта.

Проблема с ng-repeat заключается в удалении элементов из DOM, когда это необходимо для таблицы, это будет означать, что она изменит размер и таковую, но если данные динамические, они могут мерцать, потому что данные изменяются вокруг и размер таблицы меняется. Особенно во время пейджинга, потому что вся страница может еще не загрузиться.

Чтобы обойти это мерцание, таблица не должна менять количество строк. Вместо этого нужно ng-повторить "отображаемые" данные и просто изменить их по мере необходимости без добавления или удаления элементов из массива.