Obwohl technisch korrekt, würden die anderen Antworten von einer Erklärung des URL-zu-Route-Abgleichs von Angular profitieren. Ich glaube nicht, dass Sie vollständig verstehen können (entschuldigen Sie das Wortspiel), was pathMatch: fullpassiert, wenn Sie nicht wissen, wie der Router überhaupt funktioniert.
Lassen Sie uns zunächst einige grundlegende Dinge definieren. Wir werden diese URL als Beispiel verwenden : /users/james/articles?from=134#section.
Es mag offensichtlich sein, aber lassen Sie uns zunächst darauf hinweisen, dass die Abfrageparameter ( ?from=134) und Fragmente ( #section) beim Pfadabgleich keine Rolle spielen . Nur die Basis-URL ( /users/james/articles) ist wichtig.
Angular teilt URLs in Segmente auf . Die Segmente /users/james/articlessind, natürlich users, jamesund articles.
Die Routerkonfiguration ist eine Baumstruktur mit einem einzelnen Stammknoten. Jedes RouteObjekt ist ein Knoten, der childrenKnoten haben kann , die wiederum andere childrenoder Blattknoten haben können.
Das Ziel des Routers ist es, einen Router - Konfiguration zu finden Zweig , am Wurzelknoten beginnen, die passen würden genau all (!!!) Segmente der URL. Das ist entscheidend! Wenn Angular keine Route Konfigurationszweig finden , die die passen könnten ganze URL - nicht mehr und nicht weniger - es wird nicht machen nichts .
Wenn beispielsweise Ihre Ziel-URL lautet /a/b/c, der Router jedoch nur entweder /a/boder übereinstimmen kann /a/b/c/d, gibt es keine Übereinstimmung, und die Anwendung rendert nichts.
Schließlich redirectToverhalten sich Routen mit etwas anders als normale Routen, und es scheint mir, dass sie der einzige Ort sind, an dem jemand wirklich jemals etwas nutzen möchte pathMatch: full. Aber wir werden später darauf zurückkommen.
Standard ( prefix) Pfadübereinstimmung
Der Grund für den Namen prefixist, dass eine solche Routenkonfiguration prüft, ob die Konfiguration pathein Präfix der verbleibenden URL-Segmente ist. Der Router kann jedoch nur vollständige Segmente abgleichen , was diese Benennung etwas verwirrend macht.
Nehmen wir an, dies ist unsere Routerkonfiguration auf Root-Ebene:
const routes: Routes = [
{
path: 'products',
children: [
{
path: ':productID',
component: ProductComponent,
},
],
},
{
path: ':other',
children: [
{
path: 'tricks',
component: TricksComponent,
},
],
},
{
path: 'user',
component: UsersonComponent,
},
{
path: 'users',
children: [
{
path: 'permissions',
component: UsersPermissionsComponent,
},
{
path: ':userID',
children: [
{
path: 'comments',
component: UserCommentsComponent,
},
{
path: 'articles',
component: UserArticlesComponent,
},
],
},
],
},
];
Beachten Sie, dass jedes einzelne RouteObjekt hier die Standard-Matching-Strategie verwendet prefix. Diese Strategie bedeutet, dass der Router den gesamten Konfigurationsbaum durchläuft und versucht, ihn segmentweise mit der Ziel-URL abzugleichen, bis die URL vollständig übereinstimmt . So würde es für dieses Beispiel gemacht:
- Durchlaufen Sie das Root-Array und suchen Sie nach einer genauen Übereinstimmung für das erste URL-Segment
users.
'products' !== 'users'Überspringen Sie also diesen Zweig. Beachten Sie, dass wir eine Gleichheitsprüfung anstelle einer .startsWith()oder verwenden .includes()- nur vollständige Segmentübereinstimmungen zählen!
:otherEntspricht einem beliebigen Wert, es ist also eine Übereinstimmung. Die Ziel-URL ist jedoch noch nicht vollständig übereinstimmend (wir müssen noch übereinstimmen jamesund articles), daher sucht der Router nach untergeordneten Elementen.
- Das einzige Kind von
:otherist tricks, was !== 'james'daher kein Match ist.
- Angular kehrt dann zum Root-Array zurück und fährt von dort fort.
'user' !== 'users, Zweig überspringen.
'users' === 'users- Das Segment stimmt überein. Dies ist jedoch noch keine vollständige Übereinstimmung, daher müssen wir nach Kindern suchen (wie in Schritt 3).
'permissions' !== 'james', überspring es.
:userIDpasst zu allem, also haben wir eine Übereinstimmung für das jamesSegment. Dies ist jedoch immer noch keine vollständige Übereinstimmung, daher müssen wir nach einem passenden Kind suchen articles.
- Wir können sehen, dass
:userIDes eine Kinderroute articlesgibt, die uns eine vollständige Übereinstimmung gibt! Somit wird die Anwendung gerendert UserArticlesComponent.
Vollständige fullÜbereinstimmung von URL ( )
Beispiel 1
Stellen Sie sich jetzt vor, dass das usersRoutenkonfigurationsobjekt folgendermaßen aussieht:
{
path: 'users',
component: UsersComponent,
pathMatch: 'full',
children: [
{
path: 'permissions',
component: UsersPermissionsComponent,
},
{
path: ':userID',
component: UserComponent,
children: [
{
path: 'comments',
component: UserCommentsComponent,
},
{
path: 'articles',
component: UserArticlesComponent,
},
],
},
],
}
Beachten Sie die Verwendung von pathMatch: full. Wenn dies der Fall wäre, wären die Schritte 1 bis 5 gleich, jedoch wäre Schritt 6 anders:
'users' !== 'users/james/articles- Das Segment stimmt nicht überein, da die Pfadkonfiguration usersmit pathMatch: fullnicht mit der vollständigen URL übereinstimmt users/james/articles.
- Da es keine Übereinstimmung gibt, überspringen wir diesen Zweig.
- Zu diesem Zeitpunkt haben wir das Ende der Routerkonfiguration erreicht, ohne eine Übereinstimmung gefunden zu haben. Die Anwendung rendert nichts .
Beispiel 2
Was wäre, wenn wir dies stattdessen hätten:
{
path: 'users/:userID',
component: UsersComponent,
pathMatch: 'full',
children: [
{
path: 'comments',
component: UserCommentsComponent,
},
{
path: 'articles',
component: UserArticlesComponent,
},
],
}
users/:userIDpathMatch: fullNur mit Übereinstimmungen ist users/jameses also wieder eine Nichtübereinstimmung, und die Anwendung rendert nichts.
Beispiel 3
Betrachten wir Folgendes:
{
path: 'users',
children: [
{
path: 'permissions',
component: UsersPermissionsComponent,
},
{
path: ':userID',
component: UserComponent,
pathMatch: 'full',
children: [
{
path: 'comments',
component: UserCommentsComponent,
},
{
path: 'articles',
component: UserArticlesComponent,
},
],
},
],
}
In diesem Fall:
'users' === 'users- Das Segment stimmt überein, james/articlesbleibt aber unübertroffen. Lass uns nach Kindern suchen.
'permissions' !== 'james' - überspringen.
:userID'kann nur einem einzelnen Segment entsprechen, was wäre james. Es handelt sich jedoch um eine pathMatch: fullRoute, die übereinstimmen muss james/articles(die gesamte verbleibende URL). Das kann es nicht und daher ist es kein Match (also überspringen wir diesen Zweig)!
- Auch hier konnten wir keine Übereinstimmung für die URL finden und die Anwendung rendert nichts .
Wie Sie vielleicht bemerkt haben, pathMatch: fullsagt eine Konfiguration im Grunde Folgendes:
Ignoriere meine Kinder und passe nur zu mir. Wenn ich nicht alle verbleibenden URL-Segmente selbst abgleichen kann, fahren Sie fort.
Weiterleitungen
Alle, Routedie a definiert redirectTohaben, werden nach denselben Prinzipien mit der Ziel-URL abgeglichen. Der einzige Unterschied besteht darin, dass die Umleitung angewendet wird, sobald ein Segment übereinstimmt . Dies bedeutet, dass, wenn eine Umleitungsroute die Standardstrategie verwendet prefix, eine teilweise Übereinstimmung ausreicht, um eine Umleitung zu verursachen . Hier ist ein gutes Beispiel:
const routes: Routes = [
{
path: 'not-found',
component: NotFoundComponent,
},
{
path: 'users',
redirectTo: 'not-found',
},
{
path: 'users/:userID',
children: [
{
path: 'comments',
component: UserCommentsComponent,
},
{
path: 'articles',
component: UserArticlesComponent,
},
],
},
];
Für unsere ursprüngliche URL ( /users/james/articles) würde Folgendes passieren:
'not-found' !== 'users' - überspring es.
'users' === 'users' - Wir haben ein Match.
- Diese Übereinstimmung hat eine
redirectTo: 'not-found', die sofort angewendet wird .
- Die Ziel-URL ändert sich zu
not-found.
- Der Router beginnt erneut mit dem Abgleich und findet
not-foundsofort einen Abgleich für . Die Anwendung wird gerendert NotFoundComponent.
Überlegen Sie nun, was passieren würde, wenn die usersRoute auch Folgendes hätte pathMatch: full:
const routes: Routes = [
{
path: 'not-found',
component: NotFoundComponent,
},
{
path: 'users',
pathMatch: 'full',
redirectTo: 'not-found',
},
{
path: 'users/:userID',
children: [
{
path: 'comments',
component: UserCommentsComponent,
},
{
path: 'articles',
component: UserArticlesComponent,
},
],
},
];
'not-found' !== 'users' - überspring es.
userswürde mit dem ersten Segment der URL übereinstimmen, aber die Routenkonfiguration erfordert eine fullÜbereinstimmung. Überspringen Sie sie daher.
'users/:userID'Streichhölzer users/james. articlesist immer noch nicht abgestimmt, aber diese Route hat Kinder.
- Wir finden eine Übereinstimmung für
articlesdie Kinder. Die gesamte URL wird jetzt abgeglichen und die Anwendung wird gerendert UserArticlesComponent.
Leerer Pfad ( path: '')
Der leere Pfad ist ein Sonderfall, da er mit jedem Segment übereinstimmen kann , ohne es zu "verbrauchen" (daher müssten seine Kinder diesem Segment erneut entsprechen). Betrachten Sie dieses Beispiel:
const routes: Routes = [
{
path: '',
children: [
{
path: 'users',
component: BadUsersComponent,
}
]
},
{
path: 'users',
component: GoodUsersComponent,
},
];
Nehmen wir an, wir versuchen zuzugreifen /users:
path: ''wird immer übereinstimmen, daher stimmt die Route überein. Es wurde jedoch nicht die gesamte URL abgeglichen - wir müssen noch übereinstimmen users!
- Wir können sehen, dass es ein Kind gibt
users, das dem verbleibenden (und einzigen!) Segment entspricht, und wir haben eine vollständige Übereinstimmung. Die Anwendung wird gerendert BadUsersComponent.
Nun zurück zur ursprünglichen Frage
Das OP verwendete diese Routerkonfiguration:
const routes: Routes = [
{
path: 'welcome',
component: WelcomeComponent,
},
{
path: '',
redirectTo: 'welcome',
pathMatch: 'full',
},
{
path: '**',
redirectTo: 'welcome',
pathMatch: 'full',
},
];
Wenn wir zur Root-URL ( /) navigieren, würde der Router dies folgendermaßen beheben:
welcome stimmt nicht mit einem leeren Segment überein, überspringen Sie es also.
path: ''entspricht dem leeren Segment. Es hat eine pathMatch: 'full', was auch zufrieden ist, da wir die gesamte URL abgeglichen haben (es hatte ein einzelnes leeres Segment).
- Eine Weiterleitung
welcomeerfolgt und die Anwendung wird gerendert WelcomeComponent.
Was wäre, wenn es keine gäbe pathMatch: 'full'?
Eigentlich würde man erwarten, dass sich das Ganze genauso verhält. Allerdings Angular explizit verhindert eine solche Konfiguration ( { path: '', redirectTo: 'welcome' }) , weil , wenn Sie diese setzen Routeoben welcome, wäre es theoretisch eine Endlosschleife von Umleitungen erstellen. Angular gibt also nur einen Fehler aus , weshalb die Anwendung überhaupt nicht funktionieren würde! ( https://angular.io/api/router/Route#pathMatch )
Dies ist wirklich nicht sehr sinnvoll, da Angular einen Schutz gegen endlose Weiterleitungen implementiert hat - es wird nur eine einzige Umleitung pro Routing-Ebene ausgeführt.
Was ist mit path: '**'?
path: '**'passt absolut zu allem ( af/frewf/321532152/fsaist eine Übereinstimmung) mit oder ohne a pathMatch: 'full', daher macht es keinen Sinn, diese Konfigurationsoption zu verwenden.
Da es mit allem übereinstimmt, ist auch der Stammpfad enthalten, was { path: '', redirectTo: 'welcome' }in diesem Setup überflüssig wird.
Lustigerweise ist es vollkommen in Ordnung, diese Konfiguration zu haben:
const routes: Routes = [
{
path: '**',
redirectTo: 'welcome'
},
{
path: 'welcome',
component: WelcomeComponent,
},
];
Wenn wir zu navigieren /welcome, path: '**'wird ein Match stattfinden und eine Weiterleitung zur Begrüßung wird stattfinden. Dies sollte eine endlose Schleife von Weiterleitungen auslösen, aber Angular stoppt dies sofort und das Ganze funktioniert einwandfrei.