Sebbene tecnicamente corrette, le altre risposte trarrebbero vantaggio da una spiegazione della corrispondenza tra URL e route di Angular. Non penso che tu possa completamente (scusate il gioco di parole) capire cosa pathMatch: fullfa se non sai come funziona il router in primo luogo.
Definiamo prima alcune cose di base. Useremo questo URL, ad esempio: /users/james/articles?from=134#section.
Può essere ovvio, ma prima facciamo notare che i parametri di query ( ?from=134) e fragments ( #section) non giocano alcun ruolo nella corrispondenza del percorso . Solo l'URL di base ( /users/james/articles) è importante.
Angular divide gli URL in segmenti . I segmenti di /users/james/articlessono, ovviamente users, jamese articles.
La configurazione del router è una struttura ad albero con un singolo nodo radice. Ogni Routeoggetto è un nodo, che può avere childrennodi, che a loro volta possono avere altri childreno essere nodi foglia.
L'obiettivo del router è trovare un ramo di configurazione del router , a partire dal nodo radice, che corrisponda esattamente a tutti (!!!) i segmenti dell'URL. Questo è fondamentale! Se Angular non trova un ramo di configurazione del percorso che potrebbe corrispondere all'intero URL - né più né meno - non renderà nulla .
Ad esempio, se l'URL di destinazione è /a/b/c ma il router è in grado di corrispondere solo a /a/bo /a/b/c/d, allora non c'è corrispondenza e l'applicazione non visualizzerà nulla.
Infine, percorsi con redirectTo comportano in modo leggermente diverso rispetto alle rotte normali, e mi sembra che sarebbero l'unico posto dove chiunque vorrebbe davvero usare pathMatch: full. Ma ci arriveremo più tardi.
prefixCorrispondenza del percorso predefinito ( )
Il ragionamento alla base del nome prefixè che tale configurazione del percorso verificherà se il filepath è un prefisso dei segmenti di URL rimanenti. Tuttavia, il router è in grado di abbinare solo segmenti completi , il che rende questa denominazione leggermente confusa.
Ad ogni modo, diciamo che questa è la nostra configurazione del router a livello di root:
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,
},
],
},
],
},
];
Nota che ogni singolo Routeoggetto qui utilizza la strategia di corrispondenza predefinita, che è prefix. Questa strategia significa che il router itera sull'intero albero di configurazione e cerca di abbinarlo all'URL di destinazione segmento per segmento finché l'URL non viene completamente abbinato . Ecco come sarebbe fatto per questo esempio:
- Scorri l'array radice cercando una corrispondenza esatta per il primo segmento di URL -
users.
'products' !== 'users', quindi salta quel ramo. Nota che stiamo usando un controllo di uguaglianza invece di un.startsWith() o .includes()- contano solo le corrispondenze di segmenti completi!
:othercorrisponde a qualsiasi valore, quindi è una corrispondenza. Tuttavia, l'URL di destinazione non è ancora completamente abbinato (dobbiamo ancora trovare la corrispondenzajames e articles), quindi il router cerca i bambini.
- L'unico figlio di
:otherè tricks, che è!== 'james' , quindi non una corrispondenza.
- Angular quindi torna indietro all'array radice e continua da lì.
'user' !== 'users, salta ramo.
'users' === 'users- il segmento corrisponde. Tuttavia, questa non è ancora una corrispondenza completa, quindi dobbiamo cercare i bambini (come nel passaggio 3).
'permissions' !== 'james', salta.
:userIDcorrisponde a qualsiasi cosa, quindi abbiamo una corrispondenza per il jamessegmento. Tuttavia questa non è ancora una corrispondenza completa, quindi dobbiamo cercare un bambino che corrisponda articles.
- Possiamo vedere che
:userIDha un percorso figlio articles, che ci dà una corrispondenza completa! Quindi l'applicazione esegue il rendering UserArticlesComponent.
fullCorrispondenza URL completa ( )
Esempio 1
Immagina ora che l' usersoggetto di configurazione del percorso abbia questo aspetto:
{
path: 'users',
component: UsersComponent,
pathMatch: 'full',
children: [
{
path: 'permissions',
component: UsersPermissionsComponent,
},
{
path: ':userID',
component: UserComponent,
children: [
{
path: 'comments',
component: UserCommentsComponent,
},
{
path: 'articles',
component: UserArticlesComponent,
},
],
},
],
}
Nota l'utilizzo di pathMatch: full. In tal caso, i passaggi 1-5 sarebbero gli stessi, tuttavia il passaggio 6 sarebbe diverso:
'users' !== 'users/james/articles- il segmento non corrisponde perché la configurazione del percorso userscon pathMatch: fullnon corrisponde all'URL completo, che è users/james/articles.
- Poiché non c'è corrispondenza, stiamo saltando questo ramo.
- A questo punto siamo giunti alla fine della configurazione del router senza aver trovato una corrispondenza. L'applicazione non restituisce nulla .
Esempio 2
E se invece avessimo questo:
{
path: 'users/:userID',
component: UsersComponent,
pathMatch: 'full',
children: [
{
path: 'comments',
component: UserCommentsComponent,
},
{
path: 'articles',
component: UserArticlesComponent,
},
],
}
users/:userIDpathMatch: fullsolo con fiammiferiusers/james quindi è ancora una volta una non corrispondenza e l'applicazione non restituisce nulla.
Esempio 3
Consideriamo questo:
{
path: 'users',
children: [
{
path: 'permissions',
component: UsersPermissionsComponent,
},
{
path: ':userID',
component: UserComponent,
pathMatch: 'full',
children: [
{
path: 'comments',
component: UserCommentsComponent,
},
{
path: 'articles',
component: UserArticlesComponent,
},
],
},
],
}
In questo caso:
'users' === 'users - il segmento corrisponde, ma james/articles rimane ancora senza corrispondenza. Cerchiamo bambini.
'permissions' !== 'james' - Salta.
:userID'può corrispondere solo a un singolo segmento, che sarebbe james. Tuttavia, è una pathMatch: fullrotta e deve corrispondere james/articles(l'intero URL rimanente). Non è in grado di farlo e quindi non è una corrispondenza (quindi saltiamo questo ramo)!
- Ancora una volta, non siamo riusciti a trovare alcuna corrispondenza per l'URL e l'applicazione non restituisce nulla .
Come avrai notato, una pathMatch: fullconfigurazione fondamentalmente dice questo:
Ignora i miei figli e abbina solo me. Se non sono in grado di abbinare personalmente tutti i segmenti di URL rimanenti , vai avanti.
Reindirizzamenti
Tutto ciò Routeche ha definito a redirectToverrà confrontato con l'URL di destinazione secondo gli stessi principi. L'unica differenza qui è che il reindirizzamento viene applicato non appena un segmento corrisponde . Ciò significa che se un percorso di reindirizzamento utilizza la prefixstrategia predefinita , una corrispondenza parziale è sufficiente per provocare un reindirizzamento . Ecco un buon esempio:
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,
},
],
},
];
Per il nostro URL iniziale ( /users/james/articles), ecco cosa accadrebbe:
'not-found' !== 'users' - saltalo.
'users' === 'users' - abbiamo una corrispondenza.
- Questa corrispondenza ha un
redirectTo: 'not-found', che viene applicato immediatamente .
- L'URL di destinazione cambia in
not-found.
- Il router inizia di nuovo la corrispondenza e trova subito una corrispondenza per
not-found. L'applicazione esegue il rendering NotFoundComponent.
Consideriamo ora cosa accadrebbe se il userspercorso avesse anche 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' - saltalo.
userscorrisponderebbe al primo segmento dell'URL, ma la configurazione del percorso richiede una fullcorrispondenza, quindi saltala.
'users/:userID'partite users/james. articlesnon è ancora abbinato ma questo percorso ha dei bambini.
- Troviamo una corrispondenza per
articlesnei bambini. L'intero URL viene ora trovato e l'applicazione esegue il rendering UserArticlesComponent.
Percorso vuoto ( path: '')
Il percorso vuoto è un po 'un caso speciale perché può abbinare qualsiasi segmento senza "consumarlo" (quindi i suoi figli dovrebbero corrispondere di nuovo a quel segmento). Considera questo esempio:
const routes: Routes = [
{
path: '',
children: [
{
path: 'users',
component: BadUsersComponent,
}
]
},
{
path: 'users',
component: GoodUsersComponent,
},
];
Diciamo che stiamo cercando di accedere /users:
path: ''corrisponderà sempre, quindi il percorso corrisponde. Tuttavia, l'intero URL non è stato trovato: dobbiamo ancora trovare una corrispondenzausers !
- Possiamo vedere che c'è un figlio
users, che corrisponde al segmento rimanente (e unico!) E abbiamo una corrispondenza completa. L'applicazione esegue il rendering BadUsersComponent.
Ora torniamo alla domanda originale
L'OP ha utilizzato questa configurazione del router:
const routes: Routes = [
{
path: 'welcome',
component: WelcomeComponent,
},
{
path: '',
redirectTo: 'welcome',
pathMatch: 'full',
},
{
path: '**',
redirectTo: 'welcome',
pathMatch: 'full',
},
];
Se stiamo navigando all'URL di root ( /), ecco come il router lo risolverà:
welcome non corrisponde a un segmento vuoto, quindi saltalo.
path: ''corrisponde al segmento vuoto. Ha un pathMatch: 'full', che è anche soddisfatto perché abbiamo trovato l'intero URL (aveva un singolo segmento vuoto).
- Viene eseguito un reindirizzamento a
welcomee l'applicazione esegue il rendering WelcomeComponent.
E se non ci fosse stato pathMatch: 'full'?
In realtà, ci si aspetterebbe che l'intera faccenda si comporti esattamente allo stesso modo. Tuttavia, Angular impedisce esplicitamente tale configurazione ( { path: '', redirectTo: 'welcome' }) perché se lo metti Routesopra welcome, teoricamente creerebbe un ciclo infinito di reindirizzamenti. Quindi Angular genera solo un errore , motivo per cui l'applicazione non funzionerebbe affatto! ( https://angular.io/api/router/Route#pathMatch )
Questo non ha davvero molto senso perché Angular ha implementato una protezione contro reindirizzamenti infiniti: esegue solo un singolo reindirizzamento per livello di instradamento.
Di cosa path: '**'?
path: '**'corrisponderà assolutamente a qualsiasi cosa ( af/frewf/321532152/fsaè una corrispondenza) con o senza pathMatch: 'full', quindi non ha senso usare questa opzione di configurazione.
Inoltre, poiché corrisponde a tutto, è incluso anche il percorso di root, il che rende { path: '', redirectTo: 'welcome' } ridondante in questa configurazione.
Stranamente, va benissimo avere questa configurazione:
const routes: Routes = [
{
path: '**',
redirectTo: 'welcome'
},
{
path: 'welcome',
component: WelcomeComponent,
},
];
Se navighiamo verso /welcome, path: '**'sarà una partita e un reindirizzamento al benvenuto avverrà. Questo dovrebbe dare il via a un ciclo infinito di reindirizzamenti, ma Angular lo interrompe immediatamente e il tutto funziona bene.