2016-05-09 4 views
6

Ich habe ein selectedItem Objekt in Angular, es enthält andere Objekte und Arrays. Ich erstelle eine tiefe Kopie eines JSON Trick:Wie JS-Objekt und alle Arrays und Objekte innerhalb durchlaufen, um es mit seiner Kopie zu vergleichen?

$scope.editableItem = JSON.parse(JSON.stringify($scope.selectedItem)) 

Dann benutze ich editableItem Modell in Eingänge, innerhalb einige Werte ändern. selectedItem ändert sich nicht. Dann möchte ich über PATCH alle vorgenommenen Änderungen senden, aber nicht die Felder, die nicht geändert wurden. Also muss ich die editableItem aus allen Feldern entfernen, die in unveränderten gleich sind.

Wie geht das effizient? Ich dachte daran, Objekte mit Underscore rekursiv zu durchlaufen, aber ich würde wirklich gerne wissen, ob es eine gute Denkweise ist, bevor ich es anwende.

Alternativ könnte ich wahrscheinlich dritte Objekt erstellen, das nur berührte Felder aus dem zweiten enthalten würde, dynamisch hinzugefügt, aber ich bin mir nicht sicher, wie ich das angehen soll.

EDITED: Um klar zu sein, erwarte ich, dass die Antwort generisch ist und die komplizierteste mögliche Objektstruktur annimmt. Zum Beispiel sind hier keine Antworten von this question anwendbar, da sie entweder annehmen, dass das Objekt nur einfache Felder aufweist, oder dass Angular Watcher explizit für jedes Feld separat gesetzt werden muss.

+0

Wie möchten Sie Unterschiede in Arrays ausdrücken? Als Sparse-Arrays (die Sie nicht richtig in JSON konvertieren können)? – CherryDT

+0

Guter Punkt. Ich schätze: Wenn es keinen Unterschied gibt, dann sende das Array überhaupt nicht. Wenn es einen Unterschied gibt, senden Sie das gesamte geänderte Array. Array als Ganzes ist ein Wert, der geändert und übergeben oder unverändert und nicht übergeben werden kann. – Senthe

Antwort

0

Dies ist, was ich mit endete. Vielleicht hilft es jemandem. Ich habe DeepDiff Bibliothek verwendet. Code ist in CoffeScript, sollte leicht in JavaScript zu übersetzen sein, wenn es jemand benötigt.

$scope.getChangesObject =() -> 
     selected = $scope.selectedItem 
     editable = $scope.editableItem 
     changes = {} 
     differences = DeepDiff(selected, editable) 

     for diff in differences 
     formattedPath = "" 
     for pathPart, index in diff.path 
      if index isnt diff.path.length - 1 
      formattedPath += pathPart + "." 
      else 
      formattedPath += pathPart 
     changes[formattedPath] = editable[formattedPath] 

     changes 
1

ich etwas ähnliches mit einer Funktion wie folgt aus:

function getUpdateObject(orig, current) { 
    varChanges = {}; 

    for (var prop in orig) { 
     if (prop.indexOf("$") != 0 && orig[prop] !== current[prop]) { 
      varChanges[prop] = current[prop]; 
     } 
    } 
    return varChanges ; 
}; 

ich das man den ganzen Weg nicht denken, wird es bekommen. Ich verwende es nicht in irgendwelchen Szenarien, in denen die Objekte Memberobjekte oder Arrays haben, aber Sie sollten in der Lage sein zu testen, ob "prop" ein Objekt oder ein Array ist, und es rekursiv aufrufen. Der größte Nachteil, den ich bei diesem Ansatz sehe, ist, dass wenn du eine tiefliegende, verschachtelte Struktur hast, du eine Veränderung erst bemerken kannst, wenn du mehrere Level runter gegangen bist. Wahrscheinlich müssen Sie die gesamte potenzielle Hierarchie für eine geänderte Eigenschaft im Speicher behalten, und wenn Sie eine Änderung auf einer niedrigeren Ebene feststellen, schreiben Sie die gesamte Hierarchie in das Ausgabeobjekt.

+0

Ich kann eine dritte Objektkopie erstellen und dann löschen Sie die Felder, die die gleichen sind, das wäre wahrscheinlich einfacher als die Erstellung im laufenden Betrieb. – Senthe

+0

Klingt vernünftig. Mehr Speicherintensität obwohl. –

+0

Was macht 'property.indexOf (" $ ")? – Senthe

Verwandte Themen