AngularJs - ngWiederholen mit einem Filter, der ein neues Objekt zurückgibt

8

Ich versuche, eine Transformation auf die Objekte in meinem Filter anzuwenden, was dazu führt, dass ein Array neuer Objekte zurückgegeben wird. Dies liegt daran, dass ich die Objekte nach der Anwendung der Transformation filtern und die Ergebnisse der Transformation anzeigen möchte. Ich habe jedoch einen unendlichen Digest, weil die Objekte, die ich zeige, anders sind als die Objekte, die ich einfüge (wenn sie ihre $$ids vergleichen). Meine Gedanken, dies zu lösen, sind folgende:

  1. Verwenden Sie einen Tracking-Ausdruck wie track by item.id und weisen Sie jedem der transformierten Objekte die ids der Originalobjekte zu. Während alle meine Objekte momentan ein id haben, scheint das eine schlechte Idee zu sein, da es den Filter viel weniger allgemein macht - die ursprünglichen Objekte müssen ein id haben, die Umwandlung darf kein id setzen (wie es geht überschrieben werden), usw.

  2. Weisen Sie den transformierten Objekten das $$id des Originalobjekts zu. Dies scheint hackish, basierend auf meinem Verständnis $$id soll nur gelesen werden.

  3. Gibt basierend auf dem Ergebnis der Filterung der Transformation eine Teilmenge der ursprünglichen Objekte zurück. Dies kann zu Leistungsproblemen führen, da die Umwandlung sowohl im Filter- als auch im Anzeigeausdruck angewendet werden muss. UND Ich muss durch die transformierten / gefilterten Elemente zurückschleifen, um die richtigen ursprünglichen zurückzugeben.

Hier ist der Filter:

%Vor%

Und so versuche ich es zu benutzen:

%Vor%

Oh, und im Idealfall gibt ngClick das ursprüngliche Objekt zurück, aber ich kann immer eine Funktion umschließen, um nachzusehen.

    
jtfairbank 27.11.2013, 17:35
quelle

2 Antworten

7

Eine Lösung für dieses Problem, bei der Sie eine idempotente Funktion haben, die Angular aufgrund von Objekt-IDs nicht als idempotent ansieht (und damit das $ digest loop-Problem verursacht, wie Sie notiert haben), ist lo-strich / unterstries _.memoize , um die Ergebnisse Ihrer Funktion zwischenzuspeichern .

Dies garantiert, dass Ihr Filter für jeden gegebenen Cache-Schlüssel immer ein vollständig identisches Objekt zurückgibt (einschließlich $$id ). Auf diese Weise müssen Sie keine Spiele mit $$id spielen und Sie erhalten die Leistungsverbesserung dadurch, dass Sie die Filterergebnisse für jede $ Digest-Schleife nicht erneut berechnen müssen.

So können Sie die Ergebnisse Ihres Filters zwischenspeichern:

%Vor%

Ein wichtiger Hinweis für Ihre Situation ist, dass _.memoize standardmäßig den ersten Funktionsparameter ( objects in diesem Fall) als Cacheschlüssel verwendet. Da Ihr Filter bei verschiedenen Transformatorfunktionen und -ausdrücken wahrscheinlich unterschiedliche Ergebnisse liefert, habe ich den optionalen zweiten Parameter hinzugefügt - eine Hash-Funktion, die objects , expression und den Namen der transformer -Funktion verwendet, um einen Cache-Schlüssel zu erzeugen.

Hier ist eine vereinfachte Version Ihres Codes, die Folgendes verwendet: Geige

    
KayakDave 07.12.2013 20:58
quelle
2

Angular verwendet angular.equals , um Bereichsänderungen zu erkennen. Tracking-Ausdrücke werden verwendet, um Array-Elemente mit DOM-Elementen abzugleichen. Wenn Sie das Array filtern oder neu anordnen, wird Angular nur einige Elemente anzeigen, ausblenden oder neu anordnen, anstatt den gesamten Teilbaum neu zu erstellen.

Sehen Sie sich dieses einfache Beispiel an: Ссылка

%Vor%

Das Ändern des Elements durch einen Filter führt zu einer unendlichen Digest-Schleife, unabhängig von track by , während das gleiche in ng-init ohne Probleme funktioniert:

%Vor%

Dies zeigt, dass Sie anstelle eines Filters eine Direktive schreiben könnten.

Wenn jemand eine bessere Lösung kennt, werde ich es auch gerne lernen.

    
Adam 07.12.2013 00:57
quelle