2017-07-14 10 views
0

Derzeit Refactoring Angular-Anwendung zur Verwendung von ngrx speichern und haben zwei Optionen. Hier ist unsere Grundstruktur der Anwendung. Ich glaube, dass die meisten Angular-Anwendungen die gleiche Art und Weise gebaut:NGRX und Zustand-Management für Kind-Komponenten

AppComponent 
|-- ContainerComponent 
    |-- ChildComponent1 
    | |-- GrandChildComponent 
    |  |-- GrandGrandChildComponent 
    |-- ChildComponent2 

ContainerComponent Store<AppState> injiziert hat. Das Problem, das ich zu lösen versuche, ist, dass GrandGrandChildComponent (sagen wir, DropDownMenu-Komponente) sein Verhalten basierend auf dem Zustand der Anwendung ändern muss (dh einige Menüelemente unter bestimmten Bedingungen im Speicher deaktivieren) und ein Ereignis ausgeben, wenn darauf geklickt wird auf Menüpunkt so ContainerComponent (oder eine andere Komponente, nicht notwendig Vorfahren) könnte darauf reagieren.

Es gibt ein paar Möglichkeiten, es zu lösen:

  1. zwischen Komponenten kommunizieren @Input/@Output
  2. Inject Store in jede Komponente, die den Staat zu wissen, erfordert

Option 1 ist, was am häufigsten/empfohlenes Muster, das ich in den Dokumenten gelesen habe. Also nur ContainerComponent ist fett und alle Kinder sind dünn/dumm und verlassen sich auf den Zustand, der durch @Input kommt.

Aber von dem, was ich sehe, fügt dieser Ansatz viele Boilerplate hinzu, wo Sie unnötige Attribute hinzufügen müssen, nur um den Zustand zu Grand Child-Komponenten zu übergeben. Und es bricht auch das Prinzip der Trennung der Interessen, weil alle Zwischenkomponenten wissen müssen, was in den darunter liegenden Komponenten benötigt wird. Und es ist nicht einfach, eine generische Komponente zu erstellen, wenn sie die Details kennt, die nur für Grand Komponenten verfügbar sind.

Auf der anderen Seite scheint Ansatz 2 das Problem der Trennung von Bedenken zu lösen und es scheint auch eine sauberere Umsetzung zu sein. Aber da ich relativ neu in der Verwendung von redux Muster bin, bin ich mir nicht sicher, ob das der Weg ist und vielleicht kenne ich keine Fallstricke, denen ich begegnen könnte, wenn ich zu tief im Refactoring sein werde.

IMO, bieten beide Ansätze eine einfache Möglichkeit zum Testen von jeder Komponente, die für mich sehr groß ist.

Ich bin im Zweifel, welchen Ansatz zu nehmen. Welche Fallstricke sollte ich beachten?

Dank

Antwort

2

Hier ist, was Dan Abramov Schöpfer von Redux (NGRX von redux inspiriert so viele die gleichen Ideen gelten für NGRX) hat zu dem Thema zu sagen:

Wenn zur Einführung Behälter? Ich schlage vor, Sie beginnen mit dem Erstellen Ihrer App mit nur Präsentationskomponenten zuerst. Schließlich werden Sie feststellen, , dass Sie zu viele Requisiten die Zwischenkomponenten übergeben. Wenn Sie bemerken, dass einige Komponenten die Requisiten nicht verwenden, erhalten sie aber nur weiterleiten und Sie müssen all diese Zwischenkomponenten jedes Mal neu verkabeln, wenn die Kinder mehr Daten benötigen, ist es eine gute Zeit, einige Containerkomponenten einzuführen. Auf diese Weise erhalten Sie die Daten und die Verhaltensrequisiten zu den Blattkomponenten ohne die nicht verwandten Komponenten in der Mitte des Baumes zu belasten.Dies ist ein fortlaufender Prozess des Refactoring, also versuchen Sie nicht, es richtig zu bekommen zum ersten Mal. Wenn Sie mit diesem Muster experimentieren, entwickeln Sie einen intuitiven Sinn für die Zeit, um einige Container zu extrahieren, nur , wie Sie wissen, wenn es Zeit ist, eine Funktion zu extrahieren.

Quelle: https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0#7dc5

1

Das ist viel hängt von Ihrem Anwendungsfall für jede Komponente, ob, wie viele @Output und @Input sie haben.

Ich habe Ihre 1st-Ansatz für eine ganze Zeit verwendet und es scheint in Ordnung zu sein, wenn Ihre Kind/untergeordnete Komponente sehr einfache Interaktion (Daten von oben nach unten, dann ein Ereignis zurück zu Parent emittieren) oder eine Dumb Component (nimmt nur Input). Sicher, dass mein Container sehr groß war

Aber wenn eine Ihrer Child-Komponenten endete, viele I/O und viele andere Kind-Kind-Komponenten, die auch das gleiche haben, möchten Sie vielleicht als Big-Child behandeln (@Output() von Child wird in Big-Child-Komponente bleiben, statt an GrandParent-Komponente übergeben)

Wenn Sie zu viel @Output() von unten nach oben haben, können Sie auch Kopfschmerzen bekommen :). Der zweite Ansatz würde Ihre Komponente leichter lesbar machen.

AppComponent |-- ContainerComponent |-- ChildComponent1 | |-- GrandChildComponent | |-- GrandGrandChildComponent |-- ChildComponentWithManyIO => Make them to be self-managed |--GrandChild with only Input |--GrandChild with many Inputs/Outputs (Self-managed)

Meine Idee Staaten der Verwaltung kam von hier oben: https://www.youtube.com/watch?v=eBLTz8QRg4Q