Welches gilt als besser:
- mit einer Direktive, die direkt mit Diensten interagiert
oder
- Haben Sie eine Direktive, die bestimmte Hooks anzeigt, an die der Controller das Verhalten binden kann (was Dienste betrifft)?
Welches gilt als besser:
oder
Antworten:
Eine Direktive ist (als Faustregel) am besten geeignet, wenn sie kurz (in Bezug auf den Code) ist, (möglicherweise) wiederverwendbar ist und einen begrenzten Funktionsumfang aufweist. Wenn Sie eine Direktive erstellen, die die Benutzeroberfläche enthält und von einem Dienst abhängt (von dem ich annehme, dass er die Verbindung zum Backend herstellt), werden nicht nur zwei Funktionsrollen zugewiesen, nämlich:
Sie können es aber auch weniger wiederverwenden, da Sie es dann nicht mehr mit einem anderen Dienst oder mit einer anderen Benutzeroberfläche verwenden können (zumindest nicht so einfach).
Wenn diese Entscheidungen zu treffen, vergleiche ich oft auf den integrierten HTML - Elementen: zum Beispiel <input>
, <textarea>
oder <form>
: sie sind völlig unabhängig von einer bestimmten Backend. HTML5 hat dem <input>
Element einige zusätzliche Typen gegeben, z. B. date
, die immer noch unabhängig vom Backend sind und wo genau die Daten gespeichert sind oder wie sie verwendet werden. Sie sind reine Schnittstellenelemente. Ihre benutzerdefinierten Widgets, die mithilfe von Direktiven erstellt wurden, sollten nach Möglichkeit dem gleichen Muster folgen.
Dies ist jedoch nicht das Ende der Geschichte. Über die Analogie mit den integrierten HTML-Elementen hinaus können Sie wiederverwendbare Anweisungen erstellen, die sowohl Dienste aufrufen als auch eine reine Benutzeroberflächenanweisung verwenden, genau wie sie möglicherweise a verwendet <textarea>
. Angenommen, Sie möchten HTML wie folgt verwenden:
<document document-url="'documents/3345.html'">
<document-data></document-data>
<comments></comments>
<comment-entry></comment-entry>
</document>
Um die commentEntry
Direktive zu kodieren , können Sie eine sehr kleine Direktive erstellen, die nur den Controller enthält, der einen Service mit einem UI-Widget verbindet. So etwas wie:
app.directive('commentEntry', function (myService) {
return {
restrict: 'E',
template: '<comment-widget on-save="save(data)" on-cancel="cancel()"></comment-widget>',
require: '^document',
link: function (scope, iElement, iAttrs, documentController) {
// Allow the controller here to access the document controller
scope.documentController = documentController;
},
controller: function ($scope) {
$scope.save = function (data) {
// Assuming the document controller exposes a function "getUrl"
var url = $scope.documentController.getUrl();
myService.saveComments(url, data).then(function (result) {
// Do something
});
};
}
};
});
Im Extremfall müssen Sie möglicherweise nie ein manuelles ng-controller
Attribut im HTML haben: Sie können dies alles mithilfe von Direktiven tun, sofern jede direkt eine eindeutige "UI" -Rolle oder eine eindeutige "Daten" -Rolle hat.
Es gibt einen Nachteil, den ich erwähnen sollte: Es gibt der Anwendung mehr "bewegliche Teile", was ein bisschen Komplexität hinzufügt. Wenn jedoch jedes Teil eine klare Rolle spielt und gut ist (Einheit + E2E getestet), würde ich argumentieren, dass es sich lohnt und langfristig einen Gesamtnutzen darstellt.
Gestatten Sie mir, der Antwort von Michal Charemza nicht zuzustimmen.
Obwohl seine Antwort theoretisch richtig ist, ist sie für die reale Welt nicht sehr praktisch.
Ich sage das, weil ich früher so gedacht und versucht habe, es in einer großen realen App durchzusetzen, die ich und mein Team gerade aufbauen, und es wurde einfach zu mühsam.
Die Analogie zur HTML-Sprache ist nicht gut, da Sie sich nicht bemühen sollten, universelle, extrem wiederverwendbare Anweisungen zu erstellen, da Sie keine generische Anwendung wie einen Webbrowser erstellen.
Verwenden Sie stattdessen die Anweisungen, um eine domänenspezifische Sprache (Domain Specific Language, DSL) für Ihre App zu erstellen, die auf einer eigenen Domäne lebt.
Das bedeutet nicht, dass alle Richtlinien nicht generisch sein sollten. Einige könnten es sein, wenn es in ihrer Natur liegt. Wenn Sie eine benutzerdefinierte Datumsauswahl erstellen, sollten Sie diese generisch und für alle Apps wiederverwendbar machen.
Aber wenn Sie so etwas wie eine Login-Box erstellen, die an Ihr Back-End gebunden ist, tun Sie es einfach.
Die einzige Faustregel sollte lauten: Vervielfältige niemals Code (abstrakte kleine Teile von Fabriken und Diensten) und mache ihn durch Abhängigkeitsinjektion testbar. Glücklicherweise sind diese mit Angular ein Kinderspiel.
Halte es einfach. :)
Ich denke, die Frage, ob eine Direktive mit einem Dienst interagieren soll, hängt davon ab, was Ihr Dienst tut.
Ich habe Direktiven mit Diensten interagieren lassen, die mit HTTP-Anfragen nichts zu tun haben, und ich denke, das ist ein gutes Muster. Services / Factories eignen sich hervorragend zur Verkapselung von mehr datenorientierter Logik, und Direktiven eignen sich hervorragend zur Verkapselung von darstellungsorientierter Logik. Der in den Angular-Dokumenten angegebene Zweck von Diensten lautet: "Sie können Dienste zum Organisieren und Freigeben von Code in Ihrer App verwenden." Das ist ziemlich weit gefasst, aber Services können verwendet werden, um dieses Ziel in Direktiven zu erreichen.
Abgesehen davon verstehe ich den Wunsch, es in einigen Fällen so zu machen, dass Direktiven keine HTTP-Anfragen direkt stellen. Auch hier kommt es auf den Dienst an und darauf, wie Sie Ihre Dienste organisieren.
Gemäß AngularJS-Framework sollten wir einzelne Fabriken / Services zum Abrufen von Daten vom Server verwenden. Damit diese Fabriken innerhalb einer Anwendung wiederverwendet werden können, ohne sie erneut zu schreiben. Nun, innerhalb der Direktive können wir diese Fabriken aufrufen, um Daten von Api / Server abzurufen.