it-swarm.com.de

AngularJS: ng-repeat mit dynamischer Liste, ohne den gesamten DOM-Baum neu zu erstellen?

Ich verwende ng-repeat für eine Tabellenzeile, wobei Daten aus einem JSON-Array von einem Server abgerufen werden. Mein Ziel ist es, die Liste automatisch aktualisieren zu lassen, wenn ein Element auf dem Server hinzugefügt, entfernt oder geändert wird, ohne dass dies Auswirkungen auf die nicht geänderten Elemente hat. In der endgültigen Implementierung enthalten diese Tabellenzeilen auch bidirektional gebundene <input>- und <select>-Elemente, um Aktualisierungen an den Server zurückzusenden. Einige der verfügbaren Optionen in den <select>-Elementen werden auch mithilfe von ng-repeat-Direktiven aus einer anderen Liste generiert, die sich möglicherweise ebenfalls ändert.

Bisher wird jedes Mal, wenn ein neues Array vom Server kommt (derzeit alle zwei Sekunden abgefragt), die gesamte Wiederholungsliste gelöscht und neu generiert. Dies ist problematisch, da es die Textauswahl stört, Eingabefelder zerstört, selbst wenn sie gerade vom Benutzer bearbeitet werden, und wahrscheinlich viel langsamer als nötig ausgeführt wird.

Ich habe andere Web-Apps geschrieben, die mit JQuery und DOM-Manipulationen das tun, was ich will, aber der Code wird sehr haarig und die Entwicklung ist zeitaufwändig. Ich hoffe, dass AngularJS und Datenbindung verwendet werden, um dies in einem Bruchteil des Codes und der Zeit zu erreichen.

Hier also die Frage: ist es möglich, das Backing-Array auf diese Weise zu aktualisieren, aber nur die DOM-Elemente zu ändern, die den Elementen/Eigenschaften entsprechen, die tatsächlich geändert wurden?


Hier ist ein minimaler Testfall, der periodische Abfragen mit einem hartcodierten Array in einem Timer simuliert (siehe live unter http://jsfiddle.net/DWrmP/ ). Beachten Sie, dass die Textauswahl alle 500 ms gelöscht wird, da die Elemente gelöscht und neu erstellt werden.

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);
        }
        ]
);
32
nitrogen

Für diejenigen, die dies bei Google finden, beschreibt die folgende Seite eine Funktion in AngularJS 1.2, die bei diesem Problem hilft:

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


Bearbeiten zum Hinzufügen: Die wichtigsten Sätze aus dem verlinkten Beitrag, falls der Link jemals stirbt:

Mit der neuen "track by" -Syntax kann ich AngularJS jetzt mitteilen, welche Objekteigenschaft (oder Eigenschaftspfad) verwendet werden soll, um ein JavaScript-Objekt mit einem DOM-Knoten zu verknüpfen. Dies bedeutet, dass ich JavaScript-Objekte auslagern kann, ohne DOM-Knoten zu zerstören, solange die "track by" -Verbindung noch funktioniert.

36
dasho

Ich glaube, dieser Artikel wird erklären, wie ngRepeat funktioniert 

http://www.bennadel.com/blog/2443-Rendering-DOM-Elements-With-ngRepeat-In-AngularJS.htm

Wenn Sie also Objekte in der Sammlung aufbewahren - dann ja (dh $ hashKey bleibt bestehen) 

Sonst - nein

7
vittore

Ich habe vor, die folgende Lösung letztendlich selbst zu erstellen, obwohl sie sich immer noch in meinem Produktbestand befindet.

Das Problem bei ng-repeat ist, dass Elemente aus dem DOM entfernt werden, wenn dies für eine Tabelle erforderlich ist. Dies bedeutet, dass die Größe geändert wird. Wenn die Daten jedoch dynamisch sind, können sie flackern, da sich die Daten und die Tabellengröße ändern verschiebt sich. Besonders beim Paging, weil die gesamte Seite möglicherweise noch nicht geladen wurde.

Um dieses Flimmern zu umgehen, darf die Tabelle die Anzahl der Zeilen nicht ändern. Lassen Sie stattdessen eine Wiederholung von "angezeigten" Daten zu und ändern Sie sie einfach nach Bedarf, ohne Elemente hinzuzufügen oder aus dem Array zu entfernen.

0