Ich habe eine Anwendung mit einem komplexen Layout, in der der Benutzer Widgets (per Drag & Drop) (durch Auswahl aus einem vordefinierten Satz von mehr als 100 Widgets) platzieren kann, wobei jedes Widget eine benutzerdefinierte Implementierung ist, die einen Datensatz anzeigt (mit REST-Aufruf abgerufen). auf eine bestimmte Weise. Ich habe unzählige Blog-Beiträge, Fragen zum Stackoverflow und die offiziellen AngularJS-Dokumente gelesen, kann aber nicht herausfinden, wie ich meine Anwendung so gestalten soll, dass sie den Anforderungen entspricht. Bei Demo-Apps gibt es ein einzelnes Modul (ng-app), und beim Erstellen in der .js-Datei werden die abhängigen Module als Abhängigkeiten deklariert. Ich habe jedoch eine große Anzahl von Widgets und es ist irgendwie nicht ratsam, sie alle zu beschreiben Dort. Ich brauche Vorschläge für die folgenden Fragen:
- Wie soll ich meine App und Widgets gestalten - sollte ich ein separates AngularJS-Modul haben oder sollte jedes Widget eine Direktive zum Hauptmodul sein?
- Wenn ich mein Widget als Direktiven entwerfe, gibt es eine Möglichkeit, die Abhängigkeit innerhalb einer Direktive zu definieren. Das heißt, dass meine Richtlinie bei ihrer Umsetzung ng-Kalender verwendet?
- Wenn ich jedes Widget als separates Modul entwerfe, gibt es eine Möglichkeit, das Widget-Modul dynamisch als Abhängigkeit zum Hauptmodul hinzuzufügen?
- Wie soll ich die Controller entwerfen - wahrscheinlich einen Controller pro Widget?
- Wie soll ich den Status (Bereich) trennen, wenn ich mehrere Widgets desselben Typs in der Ansicht habe?
- Gibt es Best Practices für das Entwerfen wiederverwendbarer Widgets mit AngularJS?
BEARBEITEN
Nützliche Referenzen:
- ocLazyLoad - großartige Lazy Loading Lib für AngularJS
- Seed-Projekt - Module + verzögertes Laden bei Routenänderung (ES6, systemjs, ocLazyLoad)
- Faules Laden in AngularJS
- Dynamisches Laden von Controllern und Ansichten mit AngularJS und RequireJS
- Laden von AngularJS-Komponenten mit RequireJS nach dem Bootstrap der Anwendung
- Demo-Projekt zum verzögerten Laden von AngularJS-Ressourcen auf GitHub
- Load On Demand-Projekt
- Modul nur bei Bedarf dynamisch injizieren
- Ein weiteres faules Laden im Angular-Artikel
- Code-Organisation in Large AngularJS- und JavaScript-Anwendungen
quelle
Antworten:
Dies sind nur allgemeine Ratschläge.
Sie sprechen von Hunderten von Widgets. Es scheint natürlich, sie in mehrere Module aufzuteilen. Einige Widgets haben möglicherweise mehr gemeinsam als andere Widgets. Einige sind möglicherweise sehr allgemein gehalten und passen in andere Projekte, andere sind spezifischer.
Abhängigkeiten zu anderen Modulen werden auf Modulebene vorgenommen, aber es gibt kein Problem, wenn das Modul
A
vom ModulB
und von beiden abhängtA
undB
vom Modul abhängtC
. Direktiven sind eine natürliche Wahl für die Erstellung von Widgets in Angular. Wenn eine Direktive von einer anderen Direktive abhängt, definieren Sie sie entweder im selben Modul oder erstellen die Abhängigkeit auf modularer Ebene.Ich bin mir nicht sicher, warum Sie das tun möchten, und ich bin mir nicht sicher, wie ich es tun soll. Anweisungen und Dienste werden nicht initialisiert, bevor sie in Angular verwendet werden. Wenn Sie über eine große Bibliothek von Direktiven (Widgets) verfügen und wissen, dass Sie wahrscheinlich einige davon verwenden werden, aber nicht alle - aber Sie wissen nicht, welche verwendet werden, wenn die Anwendung initialisiert wird, können Sie tatsächlich "faul" sein Laden Sie "Ihre Anweisungen, nachdem Ihr Modul geladen wurde. Ich habe hier ein Beispiel erstellt
Der Vorteil ist, dass Sie Ihre Anwendung auch dann schnell laden können, wenn Sie viel Code haben, da Sie die Skripte nicht laden müssen, bevor Sie sie benötigen. Der Nachteil ist, dass es beim ersten Laden einer neuen Direktive zu einer erheblichen Verzögerung kommen kann.
Ein Widget benötigt wahrscheinlich einen eigenen Controller. Controller sollten im Allgemeinen klein sein. Wenn sie groß werden, können Sie überlegen, ob es Funktionen gibt, die besser in einen Service passen.
Widgets, die Bereichsvariablen benötigen, sollten ohne Zweifel ihre eigenen isolierten Bereiche haben (
scope:{ ... }
in der Direktivenkonfiguration).Isolieren Sie den Bereich, halten Sie die Abhängigkeiten auf ein notwendiges Minimum. Sehen Sie sich Miskos Video über Best Practices in Angular an
Brian Ford hat auch einen Artikel über das Schreiben einer riesigen Anwendung in Angular geschrieben
quelle
Diese Frage ist mir auch sehr wichtig. Die AngularJS-Homepage enthält einige Beispiele (man könnte sie Widgets nennen), also habe ich ihren Quellcode durchgesehen, um zu sehen, wie sie ihre Widgets getrennt haben.
Erstens deklarieren sie niemals ein "ng-app" -Attribut. Sie benutzen
um sicherzustellen, dass alles richtig geladen ist. Gute Idee, aber es ist seltsam, dass sie das ng-app-Attribut so sehr auf dich übertragen, dass sie es dann nicht einmal selbst verwenden. Wie auch immer, hier ist das Homepage-Modul, das sie mit der App laden - http://angularjs.org/js/homepage.js
Darin befindet sich eine Direktive namens appRun
Ich werde die ToDo-Liste als Beispiel verwenden. Für das HTML haben sie
und dann am Ende der Seite, die sie haben
Sie haben auch
Der Code wird verwendet, aber die ID-Attribute in diesen Skripten sind für die Ausführung der App nicht wichtig. Dies ist nur für die Quellcode-Anzeige links von der App.
Grundsätzlich haben sie eine Direktive namens appRun, die eine Funktion fetchCode verwendet
um den Code abzurufen. Dann verwenden sie angle.bootstrap (), um eine neue Anwendung zu erstellen. Sie können Module auch über eine App laden. Das JavaScript-Projektbeispiel wird wie folgt initialisiert
Hoffentlich hilft das. Ich bin mir immer noch nicht sicher, was die "beste" Technik ist, aber es scheint, als ob die AngularJS-Homepage einfach eine völlig separate Winkelanwendung (ng-app) für jedes Beispiel / Widget verwendet. Ich denke, ich werde das Gleiche tun, außer die fetchCode-Funktion zu ändern, um Sachen mit AJAX zu bekommen.
quelle
function hasModule(name) { try { angular.module(name); } catch(err) { return false; } return true; }