Verzeiht mir, wenn das dumm klingt, aber ich benutze AngularJS schon seit einer Weile und überall habe ich Leute gesehen, die mir sagen, dass ich meine Logik in eine Direktive (oder Dienst?) statt in meinen Controller einfügen soll und behalte nur die Bindungen in meinem Controller. Abgesehen vom Wiederverwendbarkeitsaspekt einer Richtlinie gibt es einen anderen Grund?
Bis jetzt habe ich nicht wirklich verstanden, warum das so ist. Ist das Schreiben einer Richtlinie nicht mit viel Aufwand verbunden? Ich habe keine Probleme beim Schreiben von Logik in meinem Controller und es ist einfach. Was sind die Nachteile dieses Ansatzes?
Der Controller ist der richtige Ort, um alles und jeden zu tun, der mit dem Umfang zusammenhängt. Es ist der Ort, wo Sie alle
schreiben %Vor% und definieren Sie alle $scope
-Funktionen, auf die Sie von Ihren Ansichten aus zugreifen müssen (wie Event-Handler). Im Allgemeinen ist der Event-Handler eine Plan-Funktion, die wiederum eine Funktion als Service bezeichnet.
In sehr seltenen Fällen können Sie dort einen Versprechens-Erfolgshandler hinzufügen.
DONT: Schreiben Sie Geschäftslogik in Controller
Es gab einen ganz bestimmten Grund, warum das frühere Beispiel so war. Es zeigte Ihnen eine Funktion $scope
, die wiederum eine Funktion in einem Dienst aufruft. Der Controller ist nicht für den Login-Mechanismus oder das Login verantwortlich. Wenn Sie diesen Code in einen Dienst schreiben, entkoppeln Sie den Dienst vom Controller, dh wo auch immer Sie den gleichen Dienst verwenden möchten, müssen Sie nur die Funktion injizieren und wegschleudern.
Regeln für den zukünftigen Controller:
Es gibt zwei gute Gründe für mich, Logik aus einem Controller herauszuhalten:
Wenn Ihre Anwendung mehrere Controller hat und jeder mit einigen Unterschieden ziemlich genau dasselbe tut, bedeutet das, dass Sie den Code, den Sie schreiben, wiederholen, wenn Sie die Logik im Controller behalten. Es ist besser, wenn Sie sich nicht wiederholen . Indem Sie diese Logik in einen Dienst einfügen, können Sie denselben Code in mehrere Controller einspeisen. Jeder Service (wirklich ein Factory ) wird jedes Mal neu erstellt, wenn er in einen Controller injiziert wird. Indem Sie Logik in einen Service pushen, können Sie Ihren Code modularisieren , was die Wartung und den Test erleichtert (siehe unten).
Guter Code wird getestet. Nicht nur von Menschen, sondern auch von Unit-Tests, die Sie schreiben. Komponententests geben Ihnen als Entwickler die Gewissheit, dass Ihr Code das tut, was Sie auch erwarten. Sie helfen Ihnen auch, Ihren Code gut zu gestalten.
Wenn Ihr Controller über 20 verschiedene Methoden mit jeweils eigener Logik verfügt, werden Tests (und Ihr Code) zu Spaghetti.
Es ist einfacher, Einheitentests zu schreiben, die eng sind, d. h. sie testen eine Sache nach der anderen. Und glücklicherweise ist es auch gut (aus den oben genannten Gründen), Ihren Code in gekapselte Teile aufzuteilen, d. H., Sie machen eine Sache und können dies isoliert tun. Unit-Tests (vor allem, wenn Sie Ihre Tests zuerst schreiben) zwingen Sie dazu, darüber nachzudenken, wie Sie Ihren Code in wartbare Teile aufteilen können, was Ihre Anwendung in einem guten Zustand lässt, wenn Sie in Zukunft Änderungen vornehmen wollen (Sie führen die Komponententests durch) und kann sehen, wo etwas kaputt ist).
Formularanwendung:
Sie haben eine Formularanwendung, die mehrere Formulare unterstützt. Sie haben einen Controller für jedes Formular. Wenn der Benutzer das Formular abschickt, werden die Daten über einen Proxy an ein CRM gesendet, das die Informationen in einer Datenbank speichert.
Wenn ein Kunde bereits im CRM vorhanden ist, möchten Sie keine Duplikate erstellen (ja, das CRM sollte die Daten bereinigen, aber Sie wollen das wo möglich vermeiden). Sobald der Benutzer seine Formulardaten übermittelt, muss also eine Logik implementiert werden, die etwa lautet:
NB: Wahrscheinlich sollte das Ganze von einem Back-End-Service gemacht werden, aber um es exemplarisch zu sagen, lassen Sie uns damit beginnen.
Ihre Bewerbung hat mehrere Formulare. Wenn Sie für jedes Formular dieselbe Logik in jedem Controller fest codieren (ja, Sie sollten pro Formular einen Controller haben, d. H. Einen pro Ansicht), wiederholen Sie sich mehrmals. Und das Schreiben von Tests, die den Controller überprüfen müssen, kann die Grundlagen (Daten posten, Änderungen an der Ansicht verwalten), aber auch das gesamte dieser Logik für jeden Controller testen.
Oder schreiben Sie stattdessen diese Logik einmal, stecken Sie sie in einen Dienst, schreiben Sie einen Test dafür und injizieren Sie sie, wo immer Sie möchten.
Sehen Sie sich die eckige Dokumentation an und sehen Sie sich die Muster an, die Angular implementiert, und warum diese gut zu befolgen sind (< a href="https://en.wikipedia.org/wiki/Design_Patterns"> Design Patterns - die großen sind modular, Dependency Injection, Factory und Singleton).
Das größte Problem mit Controllern ist, dass Sie nicht den HTML-Code definieren, an dem es arbeitet.
Wenn Sie ...
verwenden %Vor%... dann müssen Sie Ihren HTML-Code in Ihren Controller injizieren, was grundlegend altmodisch ist.
Wenn Sie ...
verwenden %Vor%... Ihre Direktive und Ihr HTML, an dem sie arbeitet, sind an verschiedenen Stellen definiert. Auch nicht was du willst.
Die Verwendung von Direktiven zwingt Sie, Ihren HTML-Code und den Code, den Sie benötigen, an der gleichen Stelle einzufügen. Da die Richtlinie auch einen eigenen Geltungsbereich hat, werden andere Variablen in Ihrem Code nicht beeinträchtigt. Wenn Sie Variablen von anderswo brauchen, müssen Sie sie auch explizit injizieren, was auch eine gute Sache ist.
Das Wort, das ich dafür verwende, warum das eine gute Sache ist, ist "atomar", aber ich bin mir nicht sicher, ob das das richtige Wort ist. Bedeutung: alle Dinge, die zusammenarbeiten sollten, sind in einer Datei. Mit templateUrl ist das nicht mehr richtig, immer noch ist das Template in der Direktive definiert.
Also in meinen Controllern gibt es keinen Code, der irgendetwas mit dem dom macht. Nur das Nötigste wie ein Code zum Zählen von Seiten / Ansichten oder das Verbinden von API-Daten mit dem Scope oder etwas mit $ routeParam-Daten. Der gesamte andere Code wird entweder in Services / Factories (Geschäftslogik) oder Direktiven (Dom-Logik) eingegeben.
Übrigens: Es ist möglich, einen Controller für Ihre Direktive zu definieren, der normalerweise nur für die 'zwischenrichtliche Kommunikation' verwendet wird (Sie können also den Status teilen), aber Sie verwenden dies nur mit Direktiven, die immer zusammenarbeiten (wie a Tab-Direktive, die innerhalb einer Tabs-Direktive wiederholt wird.)
Der Hauptgrund dafür, dass Sie keine Logik in Controller schreiben, ist, dass $scopes
in controller
get Garbage mit $destroy()
bei Routenänderungen gesammelt wird. In der Anweisung ngView
, wenn eine $routeChangeSuccess
broadcast empfangen wird, gibt es eine Funktion, die nur $ scope für die gerade aktive Ansicht behält, alle anderen $ scopes werden zerstört.
Wenn Sie zum Beispiel eine Einkaufswagen-App haben und Ihre Geschäftslogik der Controller ist, der $ scopes verwendet, verliert der Benutzer das Produkt und alle Formulardaten, die bereits auf der Bestellseite eingegeben wurden, wenn sie die Zurück-Schaltfläche usw. verwenden .
Tags und Links angularjs standards angularjs-directive angularjs-controller