Heim > Web-Frontend > js-Tutorial > Beseitigen Sie Laufzeitfehler mit typsicheren Routen in Angular

Beseitigen Sie Laufzeitfehler mit typsicheren Routen in Angular

Patricia Arquette
Freigeben: 2025-01-06 07:22:40
Original
224 Leute haben es durchsucht

Eliminate Runtime Errors with Type-safe Routes 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]"
      },
    },
  },
});
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

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.

an

createRoutes 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]"
      },
    },
  },
});
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

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önnen

Rendern 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,
      },
    ],
  },
];
Nach dem Login kopieren
Nach dem Login kopieren

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]"
      },
    },
  },
});
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

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,
      },
    ],
  },
];
Nach dem Login kopieren
Nach dem Login kopieren

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" }}
}
// ...
Nach dem Login kopieren

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!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage