En Angular, ¿qué es 'pathmatch: full' y qué efecto tiene?

101

Aquí está el uso de pathmatch como completo y cuando elimino este pathmatch ni siquiera carga la aplicación o ejecuta el proyecto

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
fuente

Respuestas:

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

Caso 1 pathMatch:'full' : En este caso, cuando la aplicación se inicia en localhost:4200(o algún servidor), la página predeterminada será la pantalla de bienvenida, ya que la URL seráhttps://localhost:4200/

Si https://localhost:4200/gibberishesto redirigirá a la pantalla pageNotFound debido a un path:'**'comodín

Caso 2 pathMatch:'prefix' :

Si las rutas lo han hecho { path: '', redirectTo: 'welcome', pathMatch: 'prefix' }, ahora esto nunca llegará a la ruta comodín ya que cada URL coincidiría con la path:''definida.

sai amar
fuente
hola gracias por una explicación clara a este ejemplo, pero ¿puedes dar otro ejemplo con otro tipo de rutas para que quede completamente claro por favor? (como usar un ejemplo con rutas para niños, etc.). gracias
sohaieb
muy buena explicación señor, pero ¿puede decirme cómo configurar con 2 diseños diferentes, como el diseño interno y el diseño externo>
Kapil soni
87

pathMatch = 'full' da como resultado un acierto en la ruta cuando los segmentos restantes no coincidentes de la URL coinciden con la ruta del prefijo

pathMatch = 'prefix'le dice al enrutador que coincida con la ruta de redireccionamiento cuando la URL restante comience con la ruta del prefijo de la ruta de redireccionamiento.

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

pathMatch: 'full' significa que toda la ruta de la URL debe coincidir y es consumida por el algoritmo de coincidencia de rutas.

pathMatch: 'prefix' es decir, se elige la primera ruta donde la ruta coincide con el inicio de la URL, pero luego el algoritmo de coincidencia de rutas continúa buscando rutas secundarias coincidentes donde el resto de la URL coincide.

Pardeep Jain
fuente
24

Si bien es técnicamente correcto, las otras respuestas se beneficiarían de una explicación de la coincidencia de URL a ruta de Angular. No creo que puedas entender completamente (perdón por el juego de palabras) lo que pathMatch: fullhace si no sabes cómo funciona el enrutador en primer lugar.


Primero definamos algunas cosas básicas. Vamos a utilizar esta URL como ejemplo: /users/james/articles?from=134#section.

  1. Puede ser obvio, pero primero señalemos que los parámetros de consulta ( ?from=134) y los fragmentos ( #section) no juegan ningún papel en la coincidencia de rutas . Solo /users/james/articlesimporta la URL base ( ).

  2. Angular divide las URL en segmentos . Los segmentos de /users/james/articlesson, por supuesto users, jamesy articles.

  3. La configuración del enrutador es una estructura de árbol con un solo nodo raíz. Cada Routeobjeto es un nodo, que puede tener childrennodos, que a su vez pueden tener otros childreno ser nodos hoja.

El objetivo del enrutador es encontrar una rama de configuración del enrutador , comenzando en el nodo raíz, que coincidiría exactamente con todos los segmentos (!!!) de la URL. ¡Esto es crucial! Si Angular no encuentra una rama de configuración de ruta que pueda coincidir con la URL completa , ni más ni menos , no generará nada .

Por ejemplo, si su URL de destino es /a/b/cpero el enrutador solo puede coincidir con /a/bo /a/b/c/d, entonces no hay coincidencia y la aplicación no procesará nada.

Finalmente, las rutas se redirectTocomportan de manera ligeramente diferente a las rutas regulares, y me parece que serían el único lugar donde alguien realmente querría usar pathMatch: full. Pero llegaremos a esto más tarde.

Coincidencia de prefixruta predeterminada ( )

El razonamiento detrás del nombre prefixes que dicha configuración de ruta verificará si el configurado pathes un prefijo de los segmentos de URL restantes. Sin embargo, el enrutador solo puede hacer coincidir segmentos completos , lo que hace que este nombre sea un poco confuso.

De todos modos, digamos que esta es nuestra configuración de enrutador de nivel raíz:

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,
          },
        ],
      },
    ],
  },
];

Tenga en cuenta que todos los Routeobjetos aquí utilizan la estrategia de coincidencia predeterminada, que es prefix. Esta estrategia significa que el enrutador itera sobre todo el árbol de configuración e intenta compararlo con la URL objetivo segmento por segmento hasta que la URL coincida completamente . Así es como se haría para este ejemplo:

  1. Repita la matriz raíz buscando una coincidencia exacta para el primer segmento de URL - users.
  2. 'products' !== 'users', así que omita esa rama. Tenga en cuenta que estamos usando una verificación de igualdad en lugar de un .startsWith()o .includes(): ¡solo cuentan las coincidencias de segmento completo!
  3. :othercoincide con cualquier valor, por lo que es una coincidencia. Sin embargo, la URL de destino aún no coincide por completo (todavía necesitamos hacer coincidir jamesy articles), por lo que el enrutador busca niños.
    • El único hijo de :otheres tricks, que es !== 'james', por lo tanto, no es un partido.
  4. Angular luego vuelve a la matriz raíz y continúa desde allí.
  5. 'user' !== 'users, saltar rama.
  6. 'users' === 'users- el segmento coincide. Sin embargo, todavía no es una coincidencia completa, por lo que debemos buscar niños (igual que en el paso 3).
    • 'permissions' !== 'james', Saltarlo.
    • :userIDcoincide con cualquier cosa, por lo que tenemos una coincidencia para el jamessegmento. Sin embargo, esto todavía no es una coincidencia completa, por lo que debemos buscar un niño que coincida articles.
      1. Podemos ver que :userIDtiene una ruta secundaria articles, ¡lo que nos da una coincidencia completa! Por lo tanto, la aplicación se procesa UserArticlesComponent.

Coincidencia de URL completa ( full)

Ejemplo 1

Imagínese ahora que el usersobjeto de configuración de ruta se ve así:

{
  path: 'users',
  component: UsersComponent,
  pathMatch: 'full',
  children: [
    {
      path: 'permissions',
      component: UsersPermissionsComponent,
    },
    {
      path: ':userID',
      component: UserComponent,
      children: [
        {
          path: 'comments',
          component: UserCommentsComponent,
        },
        {
          path: 'articles',
          component: UserArticlesComponent,
        },
      ],
    },
  ],
}

Tenga en cuenta el uso de pathMatch: full. Si este fuera el caso, los pasos 1-5 serían los mismos, sin embargo, el paso 6 sería diferente:

  1. 'users' !== 'users/james/articles- el segmento no coincide porque la configuración de la ruta userscon pathMatch: fullno coincide con la URL completa, que es users/james/articles.
  2. Como no hay coincidencia, nos saltamos esta rama.
  3. En este punto llegamos al final de la configuración del enrutador sin haber encontrado una coincidencia. La aplicación no muestra nada .

Ejemplo 2

¿Y si tuviéramos esto en su lugar?

{
  path: 'users/:userID',
  component: UsersComponent,
  pathMatch: 'full',
  children: [
    {
      path: 'comments',
      component: UserCommentsComponent,
    },
    {
      path: 'articles',
      component: UserArticlesComponent,
    },
  ],
}

users/:userIDpathMatch: fullsolo con coincidencias, por users/jameslo que es una no coincidencia una vez más, y la aplicación no muestra nada.

Ejemplo 3

Consideremos esto:

{
  path: 'users',
  children: [
    {
      path: 'permissions',
      component: UsersPermissionsComponent,
    },
    {
      path: ':userID',
      component: UserComponent,
      pathMatch: 'full',
      children: [
        {
          path: 'comments',
          component: UserCommentsComponent,
        },
        {
          path: 'articles',
          component: UserArticlesComponent,
        },
      ],
    },
  ],
}

En este caso:

  1. 'users' === 'users- el segmento coincide, pero james/articlessigue siendo inigualable. Busquemos niños.
    • 'permissions' !== 'james' - saltar.
    • :userID'solo puede coincidir con un solo segmento, que sería james. Sin embargo, es una pathMatch: fullruta y debe coincidir james/articles(toda la URL restante). ¡No es capaz de hacer eso y, por lo tanto, no es una coincidencia (por lo que omitimos esta rama)!
  2. Nuevamente, no pudimos encontrar ninguna coincidencia para la URL y la aplicación no muestra nada .

Como habrás notado, una pathMatch: fullconfiguración básicamente dice esto:

Ignora a mis hijos y solo empareja conmigo. Si no puedo hacer coincidir todos los segmentos de URL restantes yo mismo, continúe.

Redireccionamientos

Cualquiera Routeque haya definido un redirectTose comparará con la URL de destino de acuerdo con los mismos principios. La única diferencia aquí es que el redireccionamiento se aplica tan pronto como coincide un segmento . Esto significa que si una ruta de redireccionamiento utiliza la prefixestrategia predeterminada , una coincidencia parcial es suficiente para provocar un redireccionamiento . He aquí un buen ejemplo:

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 nuestra URL inicial ( /users/james/articles), esto es lo que sucedería:

  1. 'not-found' !== 'users' - Saltarlo.
  2. 'users' === 'users' - tenemos un partido.
  3. Esta coincidencia tiene un redirectTo: 'not-found', que se aplica inmediatamente .
  4. La URL de destino cambia a not-found.
  5. El enrutador comienza a hacer coincidir de nuevo y encuentra una coincidencia de not-foundinmediato. La aplicación se procesa NotFoundComponent.

Ahora considere lo que sucedería si la usersruta también tuviera 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' - Saltarlo.
  2. userscoincidiría con el primer segmento de la URL, pero la configuración de la ruta requiere una fullcoincidencia, por lo tanto, omítala.
  3. 'users/:userID'partidos users/james. articlestodavía no coincide pero esta ruta tiene hijos.
    • Encontramos una coincidencia articlesen los niños. La URL completa ahora coincide y la aplicación se procesa UserArticlesComponent.

Ruta vacía ( path: '')

La ruta vacía es un caso un poco especial porque puede coincidir con cualquier segmento sin "consumirlo" (por lo que sus hijos tendrían que coincidir con ese segmento nuevamente). Considere este ejemplo:

const routes: Routes = [
  {
    path: '',
    children: [
      {
        path: 'users',
        component: BadUsersComponent,
      }
    ]
  },
  {
    path: 'users',
    component: GoodUsersComponent,
  },
];

Digamos que estamos intentando acceder a /users:

  • path: ''siempre coincidirá, por lo que la ruta coincide. Sin embargo, toda la URL no ha coincidido, ¡todavía tenemos que hacerlo users!
  • Podemos ver que hay un hijo users, que coincide con el segmento restante (¡y único!) Y tenemos una coincidencia completa. La aplicación se procesa BadUsersComponent.

Ahora volvamos a la pregunta original

El OP utilizó esta configuración de enrutador:

const routes: Routes = [
  {
    path: 'welcome',
    component: WelcomeComponent,
  },
  {
    path: '',
    redirectTo: 'welcome',
    pathMatch: 'full',
  },
  {
    path: '**',
    redirectTo: 'welcome',
    pathMatch: 'full',
  },
];

Si estamos navegando a la URL raíz ( /), así es como el enrutador resolvería eso:

  1. welcome no coincide con un segmento vacío, así que omítalo.
  2. path: ''coincide con el segmento vacío. Tiene un pathMatch: 'full', que también está satisfecho porque hemos hecho coincidir toda la URL (tenía un solo segmento vacío).
  3. Se welcomeproduce una redirección y la aplicación se procesa WelcomeComponent.

¿Y si no hubiera pathMatch: 'full'?

En realidad, uno esperaría que todo se comportara exactamente igual. Sin embargo, Angular previene explícitamente tal configuración ( { path: '', redirectTo: 'welcome' }) porque si pones esto Routearriba welcome, teóricamente crearía un bucle sin fin de redirecciones. Entonces, Angular simplemente arroja un error , ¡por lo que la aplicación no funcionaría en absoluto! ( https://angular.io/api/router/Route#pathMatch )

Esto realmente no tiene mucho sentido porque Angular ha implementado una protección contra redireccionamientos infinitos: solo ejecuta un único redireccionamiento por nivel de enrutamiento.

¿Qué hay de path: '**'?

path: '**'coincidirá absolutamente con cualquier cosa ( af/frewf/321532152/fsaes una coincidencia) con o sin un pathMatch: 'full', por lo que no tiene sentido usar esta opción de configuración.

Además, dado que coincide con todo, también se incluye la ruta raíz, lo que hace que sea { path: '', redirectTo: 'welcome' }redundante en esta configuración.

Curiosamente, está perfectamente bien tener esta configuración:

const routes: Routes = [
  {
    path: '**',
    redirectTo: 'welcome'
  },
  {
    path: 'welcome',
    component: WelcomeComponent,
  },
];

Si navegamos hacia /welcome, path: '**'habrá una coincidencia y se producirá un redireccionamiento a la bienvenida. Esto debería iniciar un ciclo interminable de redireccionamientos, pero Angular lo detiene inmediatamente y todo funciona bien.

Avius
fuente
3

La estrategia de búsqueda de rutas, una de "prefijo" o "completa". El valor predeterminado es 'prefijo'.

De forma predeterminada, el enrutador verifica los elementos de la URL desde la izquierda para ver si la URL coincide con una ruta determinada y se detiene cuando hay una coincidencia. Por ejemplo, '/ team / 11 / user' coincide con 'team /: id'.

La estrategia de coincidencia de ruta "completa" coincide con la URL completa. Es importante hacer esto al redirigir rutas de ruta vacía. De lo contrario, debido a que una ruta vacía es un prefijo de cualquier URL, el enrutador aplicaría la redirección incluso cuando navega hacia el destino de la redirección, creando un bucle sin fin.

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

Ayoub Ghozzi
fuente