Em Angular, o que é 'pathmatch: full' e qual o efeito que tem?

101

Aqui é usado o pathmatch como completo e quando eu excluo este pathmatch ele nem carrega o aplicativo ou executa o projeto

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpModule } from '@angular/http';
import { RouterModule } from '@angular/router';

import { AppComponent }  from './app.component';
import { WelcomeComponent } from './home/welcome.component';

/* Feature Modules */
import { ProductModule } from './products/product.module';

@NgModule({
  imports: [
    BrowserModule,
    HttpModule,
    RouterModule.forRoot([
      { path: 'welcome', component: WelcomeComponent },
      { path: '', redirectTo: 'welcome', pathMatch: 'full' },
      { path: '**', redirectTo: 'welcome', pathMatch: 'full' }
    ]),
    ProductModule
  ],
  declarations: [
    AppComponent,
    WelcomeComponent
  ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }
GCJAmarasinghe
fonte

Respostas:

110
RouterModule.forRoot([
      { path: 'welcome', component: WelcomeComponent },
      { path: '', redirectTo: 'welcome', pathMatch: 'full' },
      { path: '**', component: 'pageNotFoundComponent' }
    ])

Caso 1 pathMatch:'full' : Neste caso, quando o aplicativo for iniciado localhost:4200(ou algum servidor) a página padrão será a tela de boas-vindas, já que o url seráhttps://localhost:4200/

Se https://localhost:4200/gibberishisso irá redirecionar para a tela pageNotFound por causa do path:'**'curinga

Caso 2 pathMatch:'prefix' :

Se as rotas já foram { path: '', redirectTo: 'welcome', pathMatch: 'prefix' }, agora isso nunca alcançará a rota curinga, pois cada url corresponderia ao path:''definido.

sai amar
fonte
Olá, obrigado pela explicação clara para este exemplo, mas você pode dar outro exemplo com outro tipo de rotas para torná-lo completamente claro, por favor? (como usar um exemplo com rotas infantis etc.). obrigado
sohaieb
Explicação muito boa, senhor, mas você pode me dizer como configurar com 2 layouts diferentes. como layout interno e layout externo>
Kapil soni
87

pathMatch = 'full' resulta em um acerto de rota quando os segmentos restantes sem correspondência do URL correspondem ao caminho do prefixo

pathMatch = 'prefix'diz ao roteador para combinar a rota de redirecionamento quando o URL restante começa com o caminho do prefixo da rota de redirecionamento.

Ref: https://angular.io/guide/router#set-up-redirects

pathMatch: 'full' significa que todo o caminho da URL precisa corresponder e é consumido pelo algoritmo de correspondência de rota.

pathMatch: 'prefix' significa que a primeira rota em que o caminho corresponde ao início da URL é escolhida, mas o algoritmo de correspondência de rota continua pesquisando as rotas secundárias em que o restante da URL corresponde.

Pardeep Jain
fonte
24

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.

  1. 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.

  2. Angular divide URLs em segmentos . Os segmentos de /users/james/articlessão, é claro users, jamese articles.

  3. 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:

  1. Itere sobre a matriz raiz procurando uma correspondência exata para o primeiro segmento de URL - users.
  2. '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!
  3. :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.
  4. O Angular então retorna à matriz raiz e continua a partir daí.
  5. 'user' !== 'users, pular ramo.
  6. '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.
      1. 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:

  1. '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 .
  2. Como não há correspondência, estamos pulando este ramo.
  3. 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:

  1. '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)!
  2. 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:

  1. 'not-found' !== 'users' - pule isso.
  2. 'users' === 'users' - nós temos um fósforo.
  3. Esta correspondência tem um redirectTo: 'not-found', que é aplicado imediatamente .
  4. O URL de destino muda para not-found .
  5. 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,
      },
    ],
  },
];
  1. 'not-found' !== 'users' - pule isso.
  2. users corresponderia ao primeiro segmento do URL, mas a configuração da rota requer um full correspondência, portanto, ignore-a.
  3. '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:

  1. welcome não corresponde a um segmento vazio, portanto, ignore-o.
  2. path: ''corresponde ao segmento vazio. Tem umpathMatch: 'full' , que também é satisfeito, pois combinamos o URL inteiro (ele tinha um único segmento vazio).
  3. 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.

Avius
fonte
3

A estratégia de correspondência de caminho, um de 'prefixo' ou 'completo'. O padrão é 'prefixo'.

Por padrão, o roteador verifica os elementos da URL à esquerda para ver se a URL corresponde a um determinado caminho e para quando há uma correspondência. Por exemplo, '/ equipe / 11 / usuário' corresponde a 'equipe /: id'.

A estratégia de correspondência de caminho 'full' corresponde a todo o URL. É importante fazer isso ao redirecionar rotas de caminho vazio. Caso contrário, como um caminho vazio é um prefixo de qualquer URL, o roteador aplicaria o redirecionamento mesmo ao navegar para o destino do redirecionamento, criando um loop infinito.

Fonte: https://angular.io/api/router/Route#properties

Ayoub Ghozzi
fonte