Beseitigen Sie Laufzeitfehler mit typsicheren Routen in Angular
Das Refactoring einer Angular-Anwendung kann ein zweischneidiges Schwert sein. Einerseits können Sie damit die Wartbarkeit und Skalierbarkeit Ihrer Codebasis verbessern. Andererseits kann es zu unterbrochenen Routen kommen, wenn Sie nicht die notwendigen Vorkehrungen getroffen haben, um Ihre Funktionen vor unbeabsichtigten Änderungen zu schützen. Das Schreiben umfassender Tests oder die Implementierung eines soliden Typisierungskonzepts für Routen können dazu beitragen, dieses Risiko zu mindern. Diese Ansätze können jedoch zeitaufwändig sein und sind möglicherweise nicht immer umsetzbar. In diesem Artikel untersuchen wir eine effizientere Lösung, die fehlerhafte Routen automatisch in der Kompilierungszeit erkennt, ohne dass manuelle Tests erforderlich sind oder benutzerdefinierte Typanmerkungen geschrieben werden müssen. Wir demonstrieren diesen Ansatz, indem wir eine Angular-Beispielanwendung mit verschachtelten Komponenten implementieren und die Typesafe-Routes-Bibliothek verwenden, um die Entwicklererfahrung zu verbessern und die Parameteranalyse zu erleichtern.
Um die Vorteile der automatischen Erkennung unterbrochener Routen in der Kompilierungszeit zu veranschaulichen, implementieren wir eine Angular-Beispielanwendung mit drei verschachtelten Komponenten: DashboardComponent (/dashboard), OrgsComponent (/orgs/:orgId) und LocationsComponent (/orgs /:orgId/locations/:locationId). Um dieses Beispiel einzurichten, müssen wir die Bibliothek „typesafe-routes“ installieren und deren Funktion „createRoutes“ verwenden, um unseren Routenbaum zu definieren, wie im folgenden Codefragment gezeigt.
// app.routes.ts import { createRoutes, int } from "typesafe-routes"; export const r = createRoutes({ dashboard: { path: ["dashboard"], // ~> "/dashboard" }, orgs: { path: ["orgs", int("orgId")], // ~> "/orgs/:orgId" children: { locations: { path: ["locations", int("locationId")], // ~> "locations/:locationId" query: [int.optional("page")], // ~> "?page=[number]" }, }, }, });
Schauen wir uns das Codefragment genauer an. Wir importieren createRoutes aus typesafe-routes und übergeben unsere Routen als erstes Argument. Diese Routen werden als verschachteltes Objekt mit zwei Eigenschaften auf der Stammebene definiert: Dashboard und Orgs. Jeder dieser Eigenschaften ist ein Pfad zugeordnet, der die Segmente in Form eines Arrays angibt. Beispielsweise entspricht das Array ["dashboard"] dem Pfad /dashboard. Der orgs-Pfad ist komplexer, da er einen Parameter namens orgId vom Typ Integer enthält. Beachten Sie, dass es sich bei „Integer“ nicht um einen nativen JavaScript-Typ, sondern um einen benutzerdefinierten Typ handelt, der mithilfe der Funktion „int“ definiert wird und die Eigenschaften einer Ganzzahl mithilfe einer Zahl im Hintergrund nachahmt. Die Orgs-Route verfügt über eine Kindereigenschaft, die eine untergeordnete Route namens „Locations“ angibt. Die Standortroute ähnelt der Organisationsroute, gibt jedoch eine zusätzliche optionale Suchparameterseite vom Typ int.
ancreateRoutes verwendet die Informationen über die Routen, um einen Kontext zu erstellen, der in ein Proxy-Objekt eingeschlossen ist. Sie müssen die Details zu diesem Proxy-Objekt nicht kennen, aber es ist wichtig zu verstehen, dass Sie dank dieses Objekts überall in Ihrer Anwendung auf alle Routenspezifikationen zugreifen können, um Routen und Parameter zu rendern und zu analysieren.
Wir haben das von createRoutes zurückgegebene Proxy-Objekt r zugewiesen. Das bedeutet, dass Sie mit r.dashboard auf den Dashboard-Pfad zugreifen können, mit r.orgs.locations auf den Standortpfad usw.
Rendering-Vorlagen
Nachdem wir unsere Routen definiert haben, können wir nun mit dem nächsten Schritt fortfahren: der Registrierung bei angle-router.
// app.routes.ts import { createRoutes, int } from "typesafe-routes"; export const r = createRoutes({ dashboard: { path: ["dashboard"], // ~> "/dashboard" }, orgs: { path: ["orgs", int("orgId")], // ~> "/orgs/:orgId" children: { locations: { path: ["locations", int("locationId")], // ~> "locations/:locationId" query: [int.optional("page")], // ~> "?page=[number]" }, }, }, });
Das Codefragment zeigt ein allgemeines Setup mit verschachtelten Routen für Angular Router, das den Routenbaum widerspiegelt, den wir zuvor definiert haben. Anstatt jedoch typische einfache Zeichenfolgen zur Angabe der Pfadvorlagen zu verwenden (z. B. orgs/:orgId), importieren wir die Vorlagenfunktion aus typesafe-routes/angular-router und verwenden sie zum Generieren der Pfadvorlagen. Für DashboardComponent und OrgsComponent können wir einfach template mit den entsprechenden Pfaden r.dashboard und r.orgs aufrufen, um die Vorlagen abzurufen. Die verbleibende Komponente LocationsComponent ist jedoch ein untergeordnetes Element von OrgsComponent und erfordert daher einen relativen Pfad, der nicht mit r.orgs.locations generiert werden kann, da dies zu einem absoluten Pfad orgs/:orgId/locations/:locationId führen würde, wohingegen Angular Router erwartet beim Verschachteln von Routenvorlagen einen relativen Pfad.
Um einen relativen Pfad zu generieren, können wir den Link _ verwenden, der effektiv alles weglässt, was vor dem Unterstrich steht. In diesem Fall können wir template(r.orgs._.locations) verwenden, um den relativen Pfad zu generieren. Dies ist eine praktische Funktion, da sie es uns ermöglicht, denselben Routenbaum in Szenarien wiederzuverwenden, in denen wir absolute Pfade rendern müssen, aber auch in Situationen, die einen relativen Pfad erfordern.
Zu diesem Zeitpunkt haben wir bereits die Vorteile der automatischen Vervollständigung und Tippfehlerverhinderung in unserer Lieblings-IDE (z. B. Visual Studio Code) genutzt. Und zukünftige Änderungen machen uns auf etwaige Rechtschreib- oder Tippfehler in unseren Routenpfaden aufmerksam, da alle Typen mit createRoutes.
auf die ursprüngliche Routendefinition zurückgeführt werden könnenRendern von Links
Da wir nun unsere Routenvorlagen spezifiziert haben, wollen wir mit dem Link-Rendering fortfahren. Dazu möchten wir eine einfache Komponente erstellen, die Renderfunktionen zum Rendern dieser Links verwendet, einschließlich Typserialisierung und Typprüfungen. Das nächste Beispiel zeigt eine Komponente, die eine Liste von Ankerelementen rendert, die auf andere Komponenten in unserer Anwendung verweisen.
// app.routes.ts import { Routes } from "@angular/router"; import { template } from "typesafe-routes/angular-router"; export const routes: Routes = [ { path: template(r.dashboard), // ~> "dashboard" component: DashboardComponent, }, { path: template(r.orgs), // ~> "orgs/:orgId" component: OrgsComponent, children: [ { path: template(r.orgs._.locations), // ~> "locations/:locationId" component: LocationsComponent, }, ], }, ];
Das Codebeispiel importiert render und renderPath aus typesafe-routes/angular-router. renderPath rendert einen Pfad, während render zusätzlich die Abfrageparameter für unsere Linkliste serialisiert. Wir importieren auch r, das Proxy-Objekt, das es uns ermöglicht, auf die Informationen über die zuvor definierten Routen zuzugreifen und die gewünschte Route zu definieren, die gerendert werden soll.
Zuerst erstellen wir „dashboardLink“ und „orgsLink“ mithilfe der renderPath-Funktion. Als ersten Parameter wird das oben genannte Proxy-Objekt verwendet, das den Pfad der darzustellenden Route darstellt. Der zweite Parameter ist ein Datensatz mit Parameterwerten, die dem Namen und Typ des Parameters entsprechen, der zuvor mit createRoutes in app.routes.ts definiert wurde. Der Rückgabewert ist ein String, der den zur entsprechenden Komponente gehörenden Pfad enthält.
Die Renderfunktion im dritten Beispiel rendert sowohl Pfad- als auch Suchparameter und erfordert daher einen Pfad und eine Abfrageeigenschaft in den Parameterdefinitionen. Der Rückgabewert ist hier ein Objekt mit den beiden Eigenschaften path und query. Wir legen die beiden Eigenschaften als Werte der Attribute [routerLink] und [queryParams] fest.
Parsing-Parameter
Das Parsen von Parametern ist ein wesentlicher Bestandteil von typsicheren Routen. Während der Routendefinition oben haben wir einige Parameter definiert und ihnen einen ganzzahligen Typ int gegeben. Da die Parameterwerte jedoch aus verschiedenen Quellen wie dem Location-Objekt stammen, sind sie stringbasiert. Praktischerweise exportiert typesafe-routes Hilfsfunktionen, die diese Zeichenfolgen analysieren und in den gewünschten Typ umwandeln. Das Parsen basiert auf unserem zuvor erstellten Proxy-Objekt r, was bedeutet, dass wir der Bibliothek mitteilen müssen, zu welcher Route die Parameter gehören. Das nächste Beispiel demonstriert dies, indem es zwei gängige Parsing-Szenarien zeigt.
// app.routes.ts import { createRoutes, int } from "typesafe-routes"; export const r = createRoutes({ dashboard: { path: ["dashboard"], // ~> "/dashboard" }, orgs: { path: ["orgs", int("orgId")], // ~> "/orgs/:orgId" children: { locations: { path: ["locations", int("locationId")], // ~> "locations/:locationId" query: [int.optional("page")], // ~> "?page=[number]" }, }, }, });
Angesichts der location.href orgs/1/location/2?page=5 können wir in Angular mit this.route.snapshot.queryParams auf stringbasierte Abfrageparameter zugreifen und darüber werden stringbasierte Pfadparameter bereitgestellt. route.snapshot.params. Mithilfe von parseQuery mit r.orgs.locations und this.route.snapshot.queryParams können wir ein Objekt mit dem Seitenparameter als Zahl abrufen. Wenn wir parsePath mit r.orgs._.locations und this.route.snapshot.params verwenden, erhalten wir die analysierte locationId. In diesem Fall ist r.orgs._.locations ein relativer Pfad und alle Segmente vor dem _-Link werden weggelassen, was dazu führt, dass orgId im resultierenden Objekt nicht vorhanden ist.
Die Parsing-Funktionen in typesafe-routes sind vielseitig und wir können mit parse.
auch alle Parameter direkt aus der Zeichenfolge location.href auf einmal extrahieren
// app.routes.ts import { Routes } from "@angular/router"; import { template } from "typesafe-routes/angular-router"; export const routes: Routes = [ { path: template(r.dashboard), // ~> "dashboard" component: DashboardComponent, }, { path: template(r.orgs), // ~> "orgs/:orgId" component: OrgsComponent, children: [ { path: template(r.orgs._.locations), // ~> "locations/:locationId" component: LocationsComponent, }, ], }, ];
Das Extrahieren von Typinformationen zu Parametern ist über InferQueryParams, InferPathParams oder InferParams möglich. Hier ist eine Demonstration des Dienstprogrammtyps InferQueryParams.
// app.component.ts import { render, renderPath } from "typesafe-routes/angular-router"; import { r } from "./app.routes"; @Component({ selector: "app-root", imports: [RouterOutlet, RouterLink], template: ` <h1>Absolute Links</h1> <ul> <li><a [routerLink]="dashboardLink">Dashboard</a></li> <li><a [routerLink]="orgsLink">Org</a></li> <li> <a [routerLink]="locationLink.path" [queryParams]="locationLink.query"> Location </a> </li> </ul> <router-outlet></router-outlet> `, }) export class AppComponent { dashboardLink = renderPath(r.dashboard, {}); // ~> dashboard orgsLink = renderPath(r.orgs, { orgId: 123 }); // ~> orgs/123 locationLink = render(r.orgs.locations, { path: { orgId: 321, locationId: 654 }, query: { page: 42 }, }); // ~> { path: "orgs/321/location/654", query: { page: "42" }} } // ...
Zusammenfassung
Zum Abschluss dieses Tutorials haben wir einen einzelnen Routenbaum erstellt, der die einzige Wahrheitsquelle für unsere Routen darstellt. Auf dieser Grundlage haben wir Vorlagen gerendert, mit denen wir unsere Komponenten bei Angular Router registriert haben. Wir haben Pfade mit dynamischen Pfadsegmenten und Abfrageparametern gerendert. Wir haben Parameter analysiert, um sie von Zeichenfolgenwerten in die entsprechenden Typen umzuwandeln. Wir haben alles typsicher gemacht, ohne auch nur eine einzige Typdefinition zu schreiben. Wir haben einen robusten Routenbaum erstellt, der Fehler bei der Entwicklung neuer Funktionen einfach verhindert und darüber hinaus zukünftige Refactorings erleichtert.
Typesafe-routes verfügt jedoch über viele weitere Funktionen, wie z. B. viele verschiedene integrierte Parametertypen, einfache Integration benutzerdefinierter Parametertypen, Manipulation von Unterpfaden, Definition benutzerdefinierter Vorlagenzeichenfolgen und vieles mehr. Leider können wir sie in diesem Tutorial nicht alle behandeln, aber Sie können mehr lesen, indem Sie die offizielle Dokumentation besuchen.
Unterstützen Sie das Projekt
Natürlich gibt es auch viele mögliche Verbesserungen, die an den in diesem Tutorial gezeigten Beispielen umgesetzt werden können. Zum Beispiel eine benutzerdefinierte Direktive für das Rendern von Links, die eine Pfaddefinition basierend auf unserem Proxy-Objekt annimmt, z. B. r.orgs.locations. Ein weiteres Beispiel ist eine Funktion, die automatisch ein Routes-Array für Angular Router generiert, wodurch doppelter Code effektiv vermieden wird und die Notwendigkeit besteht, die Routen mit unserem Routenbaum synchron zu halten, der mit createRoutes im allerersten Codeblock erstellt wurde.
Dies sind jedoch nur einige von vielen Möglichkeiten, einen Beitrag zu leisten. Der häufigste Weg ist natürlich das Teilen, das Melden von Fehlern oder das Öffnen von PRs in unserem GitHub-Repository. Wenn Sie diese Bibliothek verwenden und glauben, dass sie Ihre Entwicklungserfahrung verbessert, können Sie mir auch einen Kaffee spendieren. Wir haben auch einen Discord-Kanal, in dem Sie Feedback hinterlassen oder Fragen stellen können.
Das obige ist der detaillierte Inhalt vonBeseitigen Sie Laufzeitfehler mit typsicheren Routen in Angular. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

Video Face Swap
Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen











Unterschiedliche JavaScript -Motoren haben unterschiedliche Auswirkungen beim Analysieren und Ausführen von JavaScript -Code, da sich die Implementierungsprinzipien und Optimierungsstrategien jeder Engine unterscheiden. 1. Lexikalanalyse: Quellcode in die lexikalische Einheit umwandeln. 2. Grammatikanalyse: Erzeugen Sie einen abstrakten Syntaxbaum. 3. Optimierung und Kompilierung: Generieren Sie den Maschinencode über den JIT -Compiler. 4. Führen Sie aus: Führen Sie den Maschinencode aus. V8 Engine optimiert durch sofortige Kompilierung und versteckte Klasse.

Python eignet sich besser für Anfänger mit einer reibungslosen Lernkurve und einer kurzen Syntax. JavaScript ist für die Front-End-Entwicklung mit einer steilen Lernkurve und einer flexiblen Syntax geeignet. 1. Python-Syntax ist intuitiv und für die Entwicklung von Datenwissenschaften und Back-End-Entwicklung geeignet. 2. JavaScript ist flexibel und in Front-End- und serverseitiger Programmierung weit verbreitet.

Die Verschiebung von C/C zu JavaScript erfordert die Anpassung an dynamische Typisierung, Müllsammlung und asynchrone Programmierung. 1) C/C ist eine statisch typisierte Sprache, die eine manuelle Speicherverwaltung erfordert, während JavaScript dynamisch eingegeben und die Müllsammlung automatisch verarbeitet wird. 2) C/C muss in den Maschinencode kompiliert werden, während JavaScript eine interpretierte Sprache ist. 3) JavaScript führt Konzepte wie Verschlüsse, Prototypketten und Versprechen ein, die die Flexibilität und asynchrone Programmierfunktionen verbessern.

Zu den Hauptanwendungen von JavaScript in der Webentwicklung gehören die Interaktion der Clients, die Formüberprüfung und die asynchrone Kommunikation. 1) Dynamisches Inhaltsaktualisierung und Benutzerinteraktion durch DOM -Operationen; 2) Die Kundenüberprüfung erfolgt vor dem Einreichung von Daten, um die Benutzererfahrung zu verbessern. 3) Die Aktualisierung der Kommunikation mit dem Server wird durch AJAX -Technologie erreicht.

Die Anwendung von JavaScript in der realen Welt umfasst Front-End- und Back-End-Entwicklung. 1) Zeigen Sie Front-End-Anwendungen an, indem Sie eine TODO-Listanwendung erstellen, die DOM-Operationen und Ereignisverarbeitung umfasst. 2) Erstellen Sie RESTFUFFUPI über Node.js und express, um Back-End-Anwendungen zu demonstrieren.

Es ist für Entwickler wichtig, zu verstehen, wie die JavaScript -Engine intern funktioniert, da sie effizientere Code schreibt und Leistungs Engpässe und Optimierungsstrategien verstehen kann. 1) Der Workflow der Engine umfasst drei Phasen: Parsen, Kompilieren und Ausführung; 2) Während des Ausführungsprozesses führt die Engine dynamische Optimierung durch, wie z. B. Inline -Cache und versteckte Klassen. 3) Zu Best Practices gehören die Vermeidung globaler Variablen, die Optimierung von Schleifen, die Verwendung von const und lass und die Vermeidung übermäßiger Verwendung von Schließungen.

Python und JavaScript haben ihre eigenen Vor- und Nachteile in Bezug auf Gemeinschaft, Bibliotheken und Ressourcen. 1) Die Python-Community ist freundlich und für Anfänger geeignet, aber die Front-End-Entwicklungsressourcen sind nicht so reich wie JavaScript. 2) Python ist leistungsstark in Bibliotheken für Datenwissenschaft und maschinelles Lernen, während JavaScript in Bibliotheken und Front-End-Entwicklungsbibliotheken und Frameworks besser ist. 3) Beide haben reichhaltige Lernressourcen, aber Python eignet sich zum Beginn der offiziellen Dokumente, während JavaScript mit Mdnwebdocs besser ist. Die Wahl sollte auf Projektbedürfnissen und persönlichen Interessen beruhen.

Sowohl Python als auch JavaScripts Entscheidungen in Entwicklungsumgebungen sind wichtig. 1) Die Entwicklungsumgebung von Python umfasst Pycharm, Jupyternotebook und Anaconda, die für Datenwissenschaft und schnelles Prototyping geeignet sind. 2) Die Entwicklungsumgebung von JavaScript umfasst Node.JS, VSCODE und WebPack, die für die Entwicklung von Front-End- und Back-End-Entwicklung geeignet sind. Durch die Auswahl der richtigen Tools nach den Projektbedürfnissen kann die Entwicklung der Entwicklung und die Erfolgsquote der Projekte verbessert werden.
