W Angular, co to jest „pathmatch: full” i jaki ma efekt?

107

Tutaj używa pathmatch jako pełnego, a kiedy usuwam to pathmatch, nawet nie ładuje aplikacji ani nie uruchamia projektu

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 { }
Chanaka Amarasinghe
źródło

Odpowiedzi:

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

Przypadek 1 pathMatch:'full' : W tym przypadku, gdy aplikacja jest uruchamiana na localhost:4200(lub na jakimś serwerze), domyślną stroną będzie ekran powitalny, ponieważ adres URL będziehttps://localhost:4200/

Jeśli https://localhost:4200/gibberishspowoduje to przekierowanie do ekranu pageNotFound z powodu path:'**'symbolu wieloznacznego

Przypadek 2 pathMatch:'prefix' :

Jeśli trasy mają { path: '', redirectTo: 'welcome', pathMatch: 'prefix' }, teraz to nigdy nie osiągnie trasy z symbolem wieloznacznym, ponieważ każdy adres URL będzie pasował do path:''zdefiniowanego.

Sai Amar
źródło
witam, dziękuję za jasne wyjaśnienie tego przykładu, ale czy możesz podać inny przykład z innym rodzajem tras, aby było to całkowicie jasne? (jak na przykładzie z trasami podrzędnymi itp.). dzięki
sohaieb
naprawdę ładne wyjaśnienie, ale czy możesz mi powiedzieć, jak skonfigurować z 2 różnymi układami. jak układ wewnętrzny i układ zewnętrzny>
Kapil soni
88

pathMatch = 'full' powoduje trafienie trasy, gdy pozostałe, niedopasowane segmenty adresu URL pasują do ścieżki prefiksu

pathMatch = 'prefix'informuje router, aby dopasował trasę przekierowania, gdy pozostały adres URL zaczyna się od ścieżki prefiksu trasy przekierowania.

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

pathMatch: 'full' oznacza, że ​​cała ścieżka URL musi pasować i jest wykorzystywana przez algorytm dopasowywania tras.

pathMatch: 'prefix' oznacza, że ​​wybierana jest pierwsza trasa, w której ścieżka jest zgodna z początkiem adresu URL, ale następnie algorytm dopasowywania tras kontynuuje wyszukiwanie pasujących tras podrzędnych, w których pasuje reszta adresu URL.

Pardeep Jain
źródło
36

Chociaż technicznie poprawne, inne odpowiedzi skorzystałyby na wyjaśnieniu dopasowania adresu URL do trasy w Angular. Nie sądzę, że możesz w pełni (przepraszam za kalambur) zrozumieć, co się pathMatch: fulldzieje, jeśli nie wiesz, jak działa router.


Najpierw zdefiniujmy kilka podstawowych rzeczy. Użyjemy tego adresu jako przykład: /users/james/articles?from=134#section.

  1. Może to być oczywiste, ale najpierw zwróćmy uwagę, że parametry zapytania ( ?from=134) i fragmenty ( #section) nie odgrywają żadnej roli w dopasowywaniu ścieżek . /users/james/articlesLiczy się tylko podstawowy adres URL ( ).

  2. Angular dzieli adresy URL na segmenty . Segmenty /users/james/articlessą, oczywiście users, jamesi articles.

  3. Konfiguracja routera to struktura drzewiasta z jednym węzłem głównym. Każdy Routeobiekt jest węzłem, który może mieć childrenwęzły, które z kolei mogą mieć inne childrenlub być węzłami-liśćmi.

Celem routera jest znalezienie gałęzi konfiguracji routera , zaczynającej się od węzła głównego, która pasowałaby dokładnie do wszystkich (!!!) segmentów adresu URL. To jest kluczowe! Jeśli Angular nie znajdzie gałęzi konfiguracji trasy, która pasowałaby do całego adresu URL - ni mniej, ni więcej - niczego nie wyrenderuje .

Np. Jeśli docelowy adres URL to, /a/b/cale router jest w stanie dopasować tylko jedno /a/blub drugie /a/b/c/d, wtedy nie ma dopasowania i aplikacja niczego nie wyrenderuje.

Wreszcie trasy redirectTozachowują się nieco inaczej niż zwykłe trasy i wydaje mi się, że byłyby jedynym miejscem, z którego naprawdę ktoś chciałby skorzystać pathMatch: full. Ale do tego dojdziemy później.

prefixDopasowanie domyślnej ( ) ścieżki

Powodem tej nazwy prefixjest to, że taka konfiguracja trasy sprawdzi, czy skonfigurowana pathjest prefiksem pozostałych segmentów adresu URL. Jednak router jest w stanie dopasować tylko pełne segmenty , co sprawia, że ​​to nazewnictwo jest nieco mylące.

W każdym razie, powiedzmy, że to jest nasza konfiguracja routera na poziomie głównym:

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

Zauważ, że każdy pojedynczy Routeobiekt używa tutaj domyślnej strategii dopasowywania, czyli prefix. Ta strategia oznacza, że ​​router dokonuje iteracji po całym drzewie konfiguracji i próbuje dopasować go do docelowego adresu URL segment po segmencie, aż adres URL zostanie w pełni dopasowany . Oto, jak można by to zrobić w tym przykładzie:

  1. Iteruj po tablicy głównej, szukając dokładnego dopasowania dla pierwszego segmentu adresu URL - users.
  2. 'products' !== 'users', więc pomiń tę gałąź. Zauważ, że używamy sprawdzania równości, a nie .startsWith()lub .includes()- liczą się tylko dopasowania pełnego segmentu!
  3. :otherpasuje do dowolnej wartości, więc jest zgodna. Jednak docelowy adres URL nie jest jeszcze w pełni dopasowany (nadal musimy dopasować jamesi articles), dlatego router szuka dzieci.
  • Jedynym dzieckiem :otherjest tricks, które jest !== 'james', więc nie pasuje.
  1. Następnie Angular wraca do tablicy głównej i stamtąd kontynuuje.
  2. 'user' !== 'users, pomiń gałąź.
  3. 'users' === 'users- segment pasuje. Jednak nie jest to jeszcze pełne dopasowanie, dlatego musimy szukać dzieci (tak samo jak w kroku 3).
  • 'permissions' !== 'james', pomiń to.
  • :userIDpasuje do wszystkiego, więc mamy dopasowanie do jamessegmentu. Jednak nadal nie jest to pełne dopasowanie, dlatego musimy szukać dziecka, które by pasowało articles.
    1. Widzimy, że :userIDma trasę podrzędną articles, która daje nam pełne dopasowanie! W ten sposób aplikacja renderuje UserArticlesComponent.

Pełne fulldopasowanie adresu URL ( )

Przykład 1

Wyobraź sobie teraz, że usersobiekt konfiguracyjny trasy wyglądał następująco:

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

Zwróć uwagę na użycie pathMatch: full. Gdyby tak było, kroki 1-5 byłyby takie same, jednak krok 6 byłby inny:

  1. 'users' !== 'users/james/articles- segment nie pasuje, ponieważ konfiguracja ścieżki usersz pathMatch: fullnie pasuje do pełnego adresu URL, czyli users/james/articles.
  2. Ponieważ nie ma dopasowania, pomijamy tę gałąź.
  3. W tym momencie dotarliśmy do końca konfiguracji routera bez znalezienia dopasowania. Aplikacja nic nie wyświetla .

Przykład 2

A co by było, gdybyśmy zamiast tego mieli to:

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

users/:userIDpathMatch: fulltylko z dopasowaniami w users/jamesten sposób ponownie nie pasuje, a aplikacja nic nie wyświetla.

Przykład 3

Rozważmy to:

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

W tym przypadku:

  1. 'users' === 'users- segment pasuje, ale james/articlesnadal nie ma sobie równych. Poszukajmy dzieci.
  • 'permissions' !== 'james' - pominąć.
  • :userID'może pasować tylko do jednego segmentu james. Jest to jednak pathMatch: fulltrasa i musi pasować james/articles(cały pozostały adres URL). Nie jest w stanie tego zrobić i dlatego nie pasuje (więc pomijamy tę gałąź)!
  1. Ponownie nie znaleźliśmy żadnego dopasowania dla adresu URL, a aplikacja nic nie renderuje .

Jak być może zauważyłeś, pathMatch: fullkonfiguracja zasadniczo mówi tak:

Ignoruj ​​moje dzieci i dopasowuj tylko do mnie. Jeśli nie jestem w stanie samodzielnie dopasować wszystkich pozostałych segmentów adresów URL, przejdź dalej.

Przekierowania

Każdy, Routektóry ma zdefiniowane a, redirectTozostanie dopasowany do docelowego adresu URL według tych samych zasad. Jedyna różnica polega na tym, że przekierowanie jest stosowane natychmiast po dopasowaniu segmentu . Oznacza to, że jeśli trasa przekierowująca używa prefixstrategii domyślnej , częściowe dopasowanie wystarczy, aby spowodować przekierowanie . Oto dobry przykład:

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

/users/james/articlesOto co by się stało w przypadku naszego początkowego adresu URL ( ):

  1. 'not-found' !== 'users' - pomiń to.
  2. 'users' === 'users' - mamy dopasowanie.
  3. To dopasowanie ma redirectTo: 'not-found', które jest stosowane natychmiast .
  4. Docelowy adres URL zmieni się na not-found.
  5. Router ponownie rozpoczyna dopasowywanie i not-foundod razu znajduje dopasowanie dla . Aplikacja renderuje się NotFoundComponent.

Zastanów się teraz, co by się stało, gdyby userstrasa miała również 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' - pomiń to.
  2. usersbędzie pasował do pierwszego segmentu adresu URL, ale konfiguracja trasy wymaga fulldopasowania, dlatego pomiń go.
  3. 'users/:userID'mecze users/james. articlesnadal nie jest dopasowany, ale ta trasa ma dzieci.
  • Znajdziemy odpowiednik articlesw dzieciach. Cały adres URL jest teraz dopasowany, a aplikacja renderuje się UserArticlesComponent.

Pusta ścieżka ( path: '')

Pusta ścieżka jest trochę szczególnym przypadkiem, ponieważ może dopasować dowolny segment bez „konsumowania” go (więc jego elementy podrzędne musiałyby ponownie dopasować ten segment). Rozważmy ten przykład:

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

Powiedzmy, że próbujemy uzyskać dostęp /users:

  • path: ''będzie zawsze pasować, więc trasa będzie pasować. Jednak cały adres URL nie został dopasowany - nadal musimy dopasować users!
  • Widzimy, że jest dziecko users, które pasuje do pozostałego (i jedynego!) Segmentu i mamy pełne dopasowanie. Aplikacja renderuje się BadUsersComponent.

Wróćmy teraz do pierwotnego pytania

OP użył tej konfiguracji routera:

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

Jeśli przechodzimy do głównego adresu URL ( /), oto jak router mógłby to rozwiązać:

  1. welcome nie pasuje do pustego segmentu, więc pomiń go.
  2. path: ''pasuje do pustego segmentu. Ma pathMatch: 'full', co również jest zadowalające, ponieważ dopasowaliśmy cały adres URL (miał jeden pusty segment).
  3. Przekierowanie do się welcomedzieje i aplikacja się renderuje WelcomeComponent.

A jeśli nie było pathMatch: 'full'?

Właściwie należałoby się spodziewać, że całość będzie się zachowywać dokładnie tak samo. Jednak Angular wyraźnie zapobiega takiej konfiguracji ( { path: '', redirectTo: 'welcome' }), ponieważ jeśli umieścisz to Routepowyżej welcome, teoretycznie utworzyłoby to nieskończoną pętlę przekierowań. Więc Angular po prostu zgłasza błąd , przez co aplikacja w ogóle nie działała! ( https://angular.io/api/router/Route#pathMatch )

Właściwie, to nie ma zbyt wiele sensu do mnie, ponieważ kątowe także wdrożył ochronę przed takimi nieskończonych przekierowań - tylko biegnie pojedynczy przekierowanie za routing poziom! To zatrzymałoby wszystkie dalsze przekierowania (jak zobaczysz w poniższym przykładzie).

O co chodzi path: '**'?

path: '**'dopasuje absolutnie wszystko ( af/frewf/321532152/fsajest dopasowaniem) z lub bez pathMatch: 'full'.

Ponadto, ponieważ pasuje do wszystkiego, dołączona jest również ścieżka główna, co czyni ją { path: '', redirectTo: 'welcome' }całkowicie zbędną w tej konfiguracji.

Co zabawne, taka konfiguracja jest całkowicie w porządku:

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

Jeśli przejdziemy do /welcome, path: '**'nastąpi dopasowanie i nastąpi przekierowanie na powitanie. Teoretycznie powinno to zapoczątkować niekończącą się pętlę przekierowań, ale Angular natychmiast to zatrzymuje (ze względu na ochronę, o której wspomniałem wcześniej) i całość działa dobrze.

Avius
źródło
Jestem trochę zdezorientowany co do pełnej ścieżki. wspomniałeś w przykładzie 3 pełnego dopasowania adresu URL, Ignore my children and only match me. If I am not able to match all of the remaining URL segments myself, then move on. gdzie w przypadku pełnego dopasowania ścieżki sekcji przekierowania wspomniałeś We find a match for articles in the children. The whole URL is now matched and the application renders UserArticlesComponent. Z tego, co zrozumiałem, nie powinno pasować również w Reidrect?
rns
Dla przypomnienia - sam wymyśliłem ignore my childrenwyjaśnienie. Wątpię, jak to widzą programiści Angular, ale jest to jedna z zasad pathMatch: 'full'. Więc w przykładzie przekierowania, do którego się odnosisz, zwróć uwagę, że pathMath: 'full'jest stosowany do drugiej trasy ( path: 'users'), która z tego powodu nie pasuje. Pasująca trasa to path: 'users/:userID', która nie używa pathMatch: 'full'i działa jak zwykle. Więc najpierw pasuje, users/jamesa potem szukamy articlesw jego potomkach (po raz kolejny nie używa pathMatch: 'full').
Avius
3

Strategia dopasowywania ścieżek, jedna z opcji „prefiks” lub „pełna”. Domyślnie jest to „prefiks”.

Domyślnie router sprawdza elementy adresu URL od lewej strony, aby sprawdzić, czy adres URL pasuje do podanej ścieżki, i zatrzymuje się, gdy istnieje dopasowanie. Na przykład „/ team / 11 / user” pasuje do „team /: id”.

Strategia dopasowania ścieżki „pełna” dopasowuje do całego adresu URL. Należy to zrobić podczas przekierowywania tras z pustymi ścieżkami. W przeciwnym razie, ponieważ pusta ścieżka jest prefiksem dowolnego adresu URL, router zastosowałby przekierowanie nawet podczas nawigacji do miejsca docelowego przekierowania, tworząc nieskończoną pętlę.

Źródło: https://angular.io/api/router/Route#properties

Ayoub Ghozzi
źródło