Embora tecnicamente corretas, as outras respostas se beneficiariam de uma explicação da correspondência de URL para rota do Angular. Acho que você não consegue entender totalmente (com o perdão do trocadilho) o que pathMatch: fullsignifica se você não sabe como o roteador funciona.
Vamos primeiro definir algumas coisas básicas. Usaremos este URL como um exemplo: /users/james/articles?from=134#section.
Pode ser óbvio, mas primeiro vamos apontar que os parâmetros de consulta ( ?from=134) e fragmentos ( #section) não desempenham nenhum papel na correspondência de caminho . Apenas o url base ( /users/james/articles) é importante.
Angular divide URLs em segmentos . Os segmentos de /users/james/articlessão, é claro users, jamese articles.
A configuração do roteador é uma estrutura em árvore com um único nó raiz. Cada Routeobjeto é um nó, que pode ter childrennós, que por sua vez podem ter outros childrennós ou ser nós folha.
O objetivo do roteador é encontrar uma ramificação de configuração do roteador , começando no nó raiz, que corresponderia exatamente a todos (!!!) segmentos da URL. Isso é crucial! Se o Angular não encontrar uma ramificação de configuração de rota que possa corresponder a todo o URL - nem mais nem menos - ele não renderizará nada .
Por exemplo, se o seu URL de destino for, /a/b/cmas o roteador só é capaz de corresponder a /a/bou /a/b/c/d, então não há correspondência e o aplicativo não renderizará nada.
Finalmente, as rotas com redirectTose comportam de maneira um pouco diferente das rotas normais e parece-me que seriam o único lugar onde alguém realmente gostaria de usar pathMatch: full. Mas veremos isso mais tarde.
prefixCorrespondência de caminho padrão ( )
O raciocínio por trás do nome prefixé que essa configuração de rota verificará se o configurado pathé um prefixo dos segmentos de URL restantes. No entanto, o roteador só pode corresponder a segmentos completos , o que torna essa nomenclatura um pouco confusa.
De qualquer forma, digamos que esta é a nossa configuração de roteador de nível raiz:
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,
},
],
},
],
},
];
Observe que cada Routeobjeto aqui usa a estratégia de correspondência padrão, que é prefix. Essa estratégia significa que o roteador itera em toda a árvore de configuração e tenta combiná-la com o URL de destino, segmento por segmento, até que o URL seja totalmente compatível . Veja como isso seria feito para este exemplo:
- Itere sobre a matriz raiz procurando uma correspondência exata para o primeiro segmento de URL -
users.
'products' !== 'users', então pule esse ramo. Observe que estamos usando uma verificação de igualdade em vez de um .startsWith()or .includes()- apenas o segmento completo corresponde à contagem!
:othercorresponde a qualquer valor, portanto, é uma correspondência. No entanto, a URL de destino ainda não foi totalmente correspondida (ainda precisamos corresponder a jamese articles), portanto, o roteador procura filhos.
- O único filho de
:otheré tricks, o que !== 'james', portanto, não é compatível.
- O Angular então retorna à matriz raiz e continua a partir daí.
'user' !== 'users, pular ramo.
'users' === 'users- o segmento corresponde. No entanto, ainda não é uma correspondência completa, portanto, precisamos procurar os filhos (o mesmo que na etapa 3).
'permissions' !== 'james', pule isso.
:userIDcorresponde a qualquer coisa, portanto, temos uma correspondência para o jamessegmento. No entanto, ainda não é uma correspondência completa, portanto, precisamos procurar uma criança que corresponda articles.
- Podemos ver que
:userIDtem uma rota infantil articles, o que nos dá uma correspondência completa! Assim, o aplicativo é renderizado UserArticlesComponent.
fullCorrespondência de URL completo ( )
Exemplo 1
Imagine agora que o usersobjeto de configuração de rota se parecia com isto:
{
path: 'users',
component: UsersComponent,
pathMatch: 'full',
children: [
{
path: 'permissions',
component: UsersPermissionsComponent,
},
{
path: ':userID',
component: UserComponent,
children: [
{
path: 'comments',
component: UserCommentsComponent,
},
{
path: 'articles',
component: UserArticlesComponent,
},
],
},
],
}
Observe o uso de pathMatch: full . Se fosse esse o caso, as etapas 1 a 5 seriam iguais, mas a etapa 6 seria diferente:
'users' !== 'users/james/articles- o segmento não corresponde porque a configuração do caminho userscom pathMatch: fullnão corresponde ao URL completo, que éusers/james/articles .
- Como não há correspondência, estamos pulando este ramo.
- Nesse ponto, chegamos ao final da configuração do roteador sem encontrar uma correspondência. O aplicativo não renderiza nada .
Exemplo 2
E se em vez disso tivéssemos:
{
path: 'users/:userID',
component: UsersComponent,
pathMatch: 'full',
children: [
{
path: 'comments',
component: UserCommentsComponent,
},
{
path: 'articles',
component: UserArticlesComponent,
},
],
}
users/:userIDcom pathMatch: fulljogos apenasusers/james portanto, é uma não correspondência mais uma vez e o aplicativo não renderiza nada.
Exemplo 3
Vamos considerar isso:
{
path: 'users',
children: [
{
path: 'permissions',
component: UsersPermissionsComponent,
},
{
path: ':userID',
component: UserComponent,
pathMatch: 'full',
children: [
{
path: 'comments',
component: UserCommentsComponent,
},
{
path: 'articles',
component: UserArticlesComponent,
},
],
},
],
}
Nesse caso:
'users' === 'users - o segmento corresponde, mas james/articles ainda permanece incomparável. Vamos procurar crianças.
'permissions' !== 'james' - pule.
:userID'só pode corresponder a um único segmento, o que seria james. No entanto, é uma pathMatch: fullrota e deve corresponder james/articles(todo o URL restante). Não é capaz de fazer isso e, portanto, não é uma correspondência (por isso pulamos este ramo)!
- Novamente, não conseguimos encontrar nenhuma correspondência para a URL e o aplicativo não renderiza nada .
Como você deve ter notado, uma pathMatch: fullconfiguração basicamente diz o seguinte:
Ignore meus filhos e só me combine. Se eu não conseguir corresponder todos os segmentos de URL restantes , siga em frente.
Redireciona
Qualquer um Routeque tenha definido um redirectToserá comparado ao URL de destino de acordo com os mesmos princípios. A única diferença aqui é que o redirecionamento é aplicado assim que um segmento corresponde . Isso significa que, se uma rota de redirecionamento estiver usando a prefixestratégia padrão , uma correspondência parcial é suficiente para causar um redirecionamento . Aqui está um bom exemplo:
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,
},
],
},
];
Para nosso URL inicial ( /users/james/articles), eis o que aconteceria:
'not-found' !== 'users' - pule isso.
'users' === 'users' - nós temos um fósforo.
- Esta correspondência tem um
redirectTo: 'not-found', que é aplicado imediatamente .
- O URL de destino muda para
not-found .
- O roteador começa a corresponder novamente e encontra uma correspondência para
not-foundimediatamente. O aplicativo é renderizado NotFoundComponent.
Agora, considere o que aconteceria se a usersrota também tivesse 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' - pule isso.
users corresponderia ao primeiro segmento do URL, mas a configuração da rota requer um full correspondência, portanto, ignore-a.
'users/:userID'jogos users/james.articlesainda não foi correspondido, mas este trajeto tem filhos.
- Encontramos um par
articlesnas crianças. A URL inteira agora é correspondida e o aplicativo é renderizado UserArticlesComponent.
Caminho vazio (path: '' )
O caminho vazio é um caso especial porque pode corresponder a qualquer segmento sem "consumi-lo" (portanto, seus filhos teriam que corresponder a esse segmento novamente). Considere este exemplo:
const routes: Routes = [
{
path: '',
children: [
{
path: 'users',
component: BadUsersComponent,
}
]
},
{
path: 'users',
component: GoodUsersComponent,
},
];
Digamos que estejamos tentando acessar /users:
path: ''sempre corresponderá, portanto, a rota corresponde. No entanto, todo o URL não foi correspondido - ainda precisamos fazer a correspondênciausers !
- Podemos ver que há um filho
users, que corresponde ao segmento restante (e único!) E temos uma correspondência completa. O aplicativo é renderizado BadUsersComponent.
Agora, de volta à pergunta original
O OP usou esta configuração de roteador:
const routes: Routes = [
{
path: 'welcome',
component: WelcomeComponent,
},
{
path: '',
redirectTo: 'welcome',
pathMatch: 'full',
},
{
path: '**',
redirectTo: 'welcome',
pathMatch: 'full',
},
];
Se estivermos navegando para o URL raiz ( /), veja como o roteador resolveria isso:
welcome não corresponde a um segmento vazio, portanto, ignore-o.
path: ''corresponde ao segmento vazio. Tem umpathMatch: 'full' , que também é satisfeito, pois combinamos o URL inteiro (ele tinha um único segmento vazio).
- Um redirecionamento
welcomeacontece e o aplicativo é renderizado WelcomeComponent.
E se não houvesse pathMatch: 'full' ?
Na verdade, seria de se esperar que a coisa toda se comportasse exatamente da mesma forma. No entanto, o Angular impede explicitamente essa configuração ( { path: '', redirectTo: 'welcome' }) porque, se você colocar isso Routeacima welcome, teoricamente criaria um loop infinito de redirecionamentos. Portanto, o Angular apenas gera um erro , e é por isso que o aplicativo não funcionava! ( https://angular.io/api/router/Route#pathMatch )
Isso realmente não faz muito sentido porque o Angular implementou uma proteção contra redirecionamentos infinitos - ele executa apenas um único redirecionamento por nível de roteamento.
Sobre o quê path: '**'?
path: '**'irá corresponder a absolutamente qualquer coisa ( af/frewf/321532152/fsaé uma correspondência) com ou sem um pathMatch: 'full', portanto, não há nenhum ponto em usar esta opção de configuração.
Além disso, como corresponde a tudo, o caminho raiz também está incluído, o que torna { path: '', redirectTo: 'welcome' }redundante nesta configuração.
Curiosamente, é perfeitamente normal ter esta configuração:
const routes: Routes = [
{
path: '**',
redirectTo: 'welcome'
},
{
path: 'welcome',
component: WelcomeComponent,
},
];
Se navegarmos para /welcome, path: '**'haverá uma correspondência e um redirecionamento para boas-vindas acontecerá. Isso deve iniciar um loop infinito de redirecionamentos, mas o Angular interrompe isso imediatamente e tudo funciona bem.