Что такое «pathmatch: full» в Angular и какой эффект он дает?

106

Здесь используется полное соответствие пути, и когда я удаляю это совпадение, оно даже не загружает приложение и не запускает проект.

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 { }
Чанака Амарасингхе
источник

Ответы:

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

Случай 1. pathMatch:'full' В этом случае, когда приложение запускается на localhost:4200(или на каком-либо сервере), страница по умолчанию будет экраном приветствия, поскольку URL-адрес будетhttps://localhost:4200/

Если https://localhost:4200/gibberishэто приведет к перенаправлению на экран pageNotFound из-за path:'**'подстановочного знака

Случай 2 pathMatch:'prefix' :

Если у маршрутов есть { path: '', redirectTo: 'welcome', pathMatch: 'prefix' }, теперь он никогда не достигнет маршрута с подстановочными знаками, поскольку каждый URL-адрес будет соответствовать path:''определенному.

Сай Амар
источник
привет, спасибо за четкое объяснение этого примера, но не могли бы вы привести еще один пример с другим типом маршрутов, чтобы он был полностью понятен? (например, используя пример с детскими маршрутами и т. д.). спасибо
sohaieb
действительно хорошее объяснение, сэр, но не могли бы вы рассказать мне, как настроить с помощью двух разных макетов. например, внутренний макет и внешний макет>
Kapil soni
88

pathMatch = 'full' приводит к попаданию в маршрут, когда оставшиеся несопоставленные сегменты URL-адреса совпадают с префиксным путем

pathMatch = 'prefix'указывает маршрутизатору соответствовать маршруту перенаправления, когда оставшийся URL-адрес начинается с пути префикса маршрута перенаправления.

Ссылка: https://angular.io/guide/router#set-up-redirects

pathMatch: 'full' означает, что весь путь URL-адреса должен совпадать и используется алгоритмом сопоставления маршрутов.

pathMatch: 'prefix' означает, что выбирается первый маршрут, путь которого соответствует началу URL-адреса, но затем алгоритм сопоставления маршрутов продолжает поиск совпадающих дочерних маршрутов, где совпадает остальная часть URL-адреса.

Пардип Джайн
источник
35

Хотя технически правильно, другие ответы выиграют от объяснения соответствия URL-адреса Angular и маршрута. Я не думаю, что вы можете полностью (простите за каламбур) понять, что pathMatch: fullделает, если вы вообще не знаете, как работает маршрутизатор.


Давайте сначала определим несколько основных вещей. Мы будем использовать этот адрес в качестве примера: /users/james/articles?from=134#section.

  1. Это может быть очевидно, но сначала отметим, что параметры запроса ( ?from=134) и фрагменты ( #section) не играют никакой роли в сопоставлении путей . Имеет значение только базовый url ( /users/james/articles).

  2. Angular разбивает URL-адреса на сегменты . Сегменты - /users/james/articlesэто, конечно users, jamesи articles.

  3. Конфигурация маршрутизатора представляет собой древовидную структуру с одним корневым узлом. Каждый Routeобъект представляет собой узел, который может иметь childrenузлы, которые, в свою очередь, могут иметь другие childrenили быть листовыми узлами.

Цель маршрутизатора - найти ветвь конфигурации маршрутизатора , начинающуюся с корневого узла, которая соответствовала бы точно всем (!!!) сегментам URL. Это очень важно! Если Angular не находит ветку конфигурации маршрута, которая могла бы соответствовать всему URL-адресу - ни больше ни меньше - он ничего не отобразит .

Например, если ваш целевой URL-адрес, /a/b/cно маршрутизатор может сопоставить только либо /a/bили /a/b/c/d, то совпадения нет, и приложение ничего не отобразит.

Наконец, маршруты с redirectToведут себя немного иначе, чем обычные маршруты, и мне кажется, что они будут единственным местом, где кто-то действительно когда-либо захочет воспользоваться pathMatch: full. Но мы вернемся к этому позже.

Соответствие prefixпути по умолчанию ( )

Причина названия prefixзаключается в том, что такая конфигурация маршрута будет проверять, является ли сконфигурированный pathпрефиксом оставшихся сегментов URL. Однако маршрутизатор может сопоставлять только полные сегменты , что немного сбивает с толку это наименование.

В любом случае, допустим, это наша конфигурация маршрутизатора корневого уровня:

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

Обратите внимание, что каждый отдельный Routeобъект здесь использует стратегию сопоставления по умолчанию, то есть prefix. Эта стратегия означает, что маршрутизатор выполняет итерацию по всему дереву конфигурации и пытается сопоставить его с целевым URL-адресом сегмент за сегментом, пока URL-адрес не будет полностью сопоставлен . Вот как это будет сделано для этого примера:

  1. Обходите корневой массив в поисках точного совпадения для первого сегмента URL - users.
  2. 'products' !== 'users', так что пропустите эту ветку. Обратите внимание, что мы используем проверку на равенство, а не .startsWith()или .includes()- учитываются только совпадения полного сегмента!
  3. :otherсоответствует любому значению, так что это совпадение. Однако целевой URL еще не полностью сопоставлен (нам все еще нужно сопоставить jamesи articles), поэтому маршрутизатор ищет дочерние элементы.
  • Единственный ребенок :otherIS tricks, который !== 'james', следовательно , не совпадают.
  1. Затем Angular возвращается к корневому массиву и продолжает оттуда.
  2. 'user' !== 'users, пропустить ветку.
  3. 'users' === 'users- сегмент совпадает. Однако это еще не полное совпадение, поэтому нам нужно искать детей (как в шаге 3).
  • 'permissions' !== 'james', пропустить это.
  • :userIDсоответствует чему угодно, таким образом, мы имеем совпадение для jamesсегмента. Однако это еще не полное совпадение, поэтому нам нужно искать дочерний элемент, который бы совпадал articles.
    1. Мы видим, что у :userIDнего есть дочерний маршрут articles, который дает нам полное совпадение! Таким образом приложение выполняет рендеринг UserArticlesComponent.

Соответствие полного URL ( full)

Пример 1

Теперь представьте, что usersобъект конфигурации маршрута выглядел так:

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

Обратите внимание на использование pathMatch: full. Если бы это было так, шаги 1-5 были бы такими же, но шаг 6 был бы другим:

  1. 'users' !== 'users/james/articles- сегмент не совпадает, потому что конфигурация пути usersс pathMatch: fullне соответствует полному URL-адресу, а именно users/james/articles.
  2. Так как совпадений нет, мы пропускаем эту ветку.
  3. На этом этапе мы достигли конца настройки маршрутизатора, не найдя совпадения. Приложение ничего не отображает .

Пример 2

Что, если бы у нас было это:

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

users/:userIDpathMatch: fullтолько с совпадениями, users/jamesпоэтому снова нет совпадений, и приложение ничего не отображает.

Пример 3

Давайте рассмотрим это:

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

В этом случае:

  1. 'users' === 'users- сегмент совпадает, но по- james/articlesпрежнему не совпадает . Поищем детей.
  • 'permissions' !== 'james' - пропускать.
  • :userID'может соответствовать только одному сегменту, который был бы james. Однако это pathMatch: fullмаршрут, и он должен совпадать james/articles(весь оставшийся URL). Он не может этого сделать, и поэтому это не совпадение (поэтому мы пропускаем эту ветку)!
  1. Опять же, нам не удалось найти совпадения для URL-адреса, и приложение ничего не отображает .

Как вы могли заметить, pathMatch: fullконфигурация в основном говорит следующее:

Не обращай внимания на моих детей и сравнивайся только со мной. Если я не могу самостоятельно сопоставить все оставшиеся сегменты URL, продолжайте.

Перенаправления

Любой Routeобъект, для которого задан a, redirectToбудет сопоставлен с целевым URL-адресом в соответствии с теми же принципами. Единственная разница в том, что перенаправление применяется, как только сегмент совпадает . Это означает, что если маршрут перенаправления использует prefixстратегию по умолчанию , частичного совпадения достаточно, чтобы вызвать перенаправление . Вот хороший пример:

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

Для нашего исходного URL ( /users/james/articles) вот что произойдет:

  1. 'not-found' !== 'users' - пропустить это.
  2. 'users' === 'users' - у нас есть матч.
  3. У этого совпадения есть redirectTo: 'not-found', который применяется немедленно .
  4. Целевой URL изменится на not-found.
  5. Маршрутизатор снова начинает сопоставление и сразу находит совпадение not-found. Приложение отображает NotFoundComponent.

Теперь подумайте, что бы произошло, если бы в usersмаршруте также были 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' - пропустить это.
  2. usersбудет соответствовать первому сегменту URL-адреса, но конфигурация маршрута требует fullсовпадения, поэтому пропустите его.
  3. 'users/:userID'совпадения users/james. articlesвсе еще не найден, но у этого маршрута есть дочерние элементы.
  • Мы находим совпадение articlesв детях. Теперь соответствует весь URL-адрес, и приложение выполняет рендеринг UserArticlesComponent.

Пустой путь ( path: '')

Пустой путь - это особый случай, потому что он может соответствовать любому сегменту, не «потребляя» его (так что дочерним элементам придется снова сопоставить этот сегмент). Рассмотрим этот пример:

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

Допустим, мы пытаемся получить доступ /users:

  • path: ''всегда будет совпадать, следовательно, маршрут совпадает. Однако весь URL-адрес не был сопоставлен - нам все еще нужно сопоставить users!
  • Мы видим, что есть дочерний элемент users, который соответствует оставшемуся (и единственному!) Сегменту, и у нас есть полное совпадение. Приложение отображает BadUsersComponent.

Теперь вернемся к исходному вопросу

OP использовал эту конфигурацию маршрутизатора:

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

Если мы переходим к корневому URL ( /), вот как маршрутизатор решит это:

  1. welcome не соответствует пустому сегменту, поэтому пропустите его.
  2. path: ''соответствует пустому сегменту. У него есть pathMatch: 'full', что также удовлетворяет, поскольку мы сопоставили весь URL (у него был единственный пустой сегмент).
  3. welcomeПроисходит перенаправление на , и приложение выполняет рендеринг WelcomeComponent.

Что, если не было pathMatch: 'full'?

Собственно, можно было бы ожидать, что все будет вести себя точно так же. Однако Angular явно запрещает такую ​​конфигурацию ( { path: '', redirectTo: 'welcome' }), потому что, если вы поместите это Routeвыше welcome, теоретически это создаст бесконечный цикл перенаправлений. Итак, Angular просто выдает ошибку , поэтому приложение вообще не работает! ( https://angular.io/api/router/Route#pathMatch )

На самом деле, для меня это не имеет особого смысла, потому что Angular также реализовал защиту от таких бесконечных перенаправлений - он выполняет только одно перенаправление для каждого уровня маршрутизации! Это остановит все дальнейшие перенаправления (как вы увидите в примере ниже).

О чем path: '**'?

path: '**'будет соответствовать абсолютно чему угодно ( af/frewf/321532152/fsaявляется совпадением) с или без pathMatch: 'full'.

Кроме того, поскольку он соответствует всему, корневой путь также включен, что делает { path: '', redirectTo: 'welcome' }эту настройку полностью избыточной.

Как ни странно, вполне нормально иметь такую ​​конфигурацию:

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

Если мы перейдем к /welcome, path: '**'будет совпадение и произойдет перенаправление на welcome. Теоретически это должно запустить бесконечный цикл перенаправлений, но Angular немедленно останавливает это (из-за защиты, о которой я упоминал ранее), и все это работает нормально.

Avius
источник
Я немного запутался в отношении полного пути. Вы упомянули в Примере 3 о полном сопоставлении 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. где, как и при сопоставлении полного пути в разделе «Перенаправление», о котором вы упомянули. We find a match for articles in the children. The whole URL is now matched and the application renders UserArticlesComponent. Насколько я понял, это не должно совпадать и в Reidrect?
rns
Для протокола - ignore my childrenобъяснение я придумал сам. Сомнение это как угловые разработчики видеть это, но это один из принципов pathMatch: 'full'. Итак, в примере перенаправления, о котором вы говорите, обратите внимание, что pathMath: 'full'он применяется ко второму маршруту ( path: 'users'), который из-за этого не соответствует. Соответствующий маршрут - это path: 'users/:userID', который не используется pathMatch: 'full'и работает как обычно. Итак, сначала он совпадает, users/jamesа затем мы ищем articlesв его дочерних элементах (опять же, он не использует pathMatch: 'full').
Avius
3

Стратегия сопоставления пути, одна из «префикс» или «полный». По умолчанию - «префикс».

По умолчанию маршрутизатор проверяет элементы URL-адреса слева, чтобы убедиться, что URL-адрес соответствует заданному пути, и останавливается при обнаружении совпадения. Например, '/ team / 11 / user' соответствует 'team /: id'.

Стратегия соответствия пути "полный" соответствует всему URL-адресу. Это важно сделать при перенаправлении маршрутов с пустым путем. В противном случае, поскольку пустой путь является префиксом любого URL-адреса, маршрутизатор будет применять перенаправление даже при переходе к месту назначения перенаправления, создавая бесконечный цикл.

Источник: https://angular.io/api/router/Route#properties

Аюб Гоззи
источник