Здесь используется полное соответствие пути, и когда я удаляю это совпадение, оно даже не загружает приложение и не запускает проект.
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 { }
angular
typescript
angular-router
Чанака Амарасингхе
источник
источник
Ссылка: https://angular.io/guide/router#set-up-redirects
pathMatch: 'full'
означает, что весь путь URL-адреса должен совпадать и используется алгоритмом сопоставления маршрутов.pathMatch: 'prefix'
означает, что выбирается первый маршрут, путь которого соответствует началу URL-адреса, но затем алгоритм сопоставления маршрутов продолжает поиск совпадающих дочерних маршрутов, где совпадает остальная часть URL-адреса.источник
Хотя технически правильно, другие ответы выиграют от объяснения соответствия URL-адреса Angular и маршрута. Я не думаю, что вы можете полностью (простите за каламбур) понять, что
pathMatch: full
делает, если вы вообще не знаете, как работает маршрутизатор.Давайте сначала определим несколько основных вещей. Мы будем использовать этот адрес в качестве примера:
/users/james/articles?from=134#section
.Это может быть очевидно, но сначала отметим, что параметры запроса (
?from=134
) и фрагменты (#section
) не играют никакой роли в сопоставлении путей . Имеет значение только базовый url (/users/james/articles
).Angular разбивает URL-адреса на сегменты . Сегменты -
/users/james/articles
это, конечноusers
,james
иarticles
.Конфигурация маршрутизатора представляет собой древовидную структуру с одним корневым узлом. Каждый
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-адрес не будет полностью сопоставлен . Вот как это будет сделано для этого примера:users
.'products' !== 'users'
, так что пропустите эту ветку. Обратите внимание, что мы используем проверку на равенство, а не.startsWith()
или.includes()
- учитываются только совпадения полного сегмента!:other
соответствует любому значению, так что это совпадение. Однако целевой URL еще не полностью сопоставлен (нам все еще нужно сопоставитьjames
иarticles
), поэтому маршрутизатор ищет дочерние элементы.:other
IStricks
, который!== 'james'
, следовательно , не совпадают.'user' !== 'users
, пропустить ветку.'users' === 'users
- сегмент совпадает. Однако это еще не полное совпадение, поэтому нам нужно искать детей (как в шаге 3).'permissions' !== 'james'
, пропустить это.:userID
соответствует чему угодно, таким образом, мы имеем совпадение дляjames
сегмента. Однако это еще не полное совпадение, поэтому нам нужно искать дочерний элемент, который бы совпадалarticles
.: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 был бы другим:'users' !== 'users/james/articles
- сегмент не совпадает, потому что конфигурация путиusers
сpathMatch: full
не соответствует полному URL-адресу, а именноusers/james/articles
.Пример 2
Что, если бы у нас было это:
{ path: 'users/:userID', component: UsersComponent, pathMatch: 'full', children: [ { path: 'comments', component: UserCommentsComponent, }, { path: 'articles', component: UserArticlesComponent, }, ], }
users/:userID
pathMatch: 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, }, ], }, ], }
В этом случае:
'users' === 'users
- сегмент совпадает, но по-james/articles
прежнему не совпадает . Поищем детей.'permissions' !== 'james'
- пропускать.:userID'
может соответствовать только одному сегменту, который был быjames
. Однако этоpathMatch: full
маршрут, и он должен совпадатьjames/articles
(весь оставшийся URL). Он не может этого сделать, и поэтому это не совпадение (поэтому мы пропускаем эту ветку)!Как вы могли заметить,
pathMatch: full
конфигурация в основном говорит следующее:Перенаправления
Любой
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
) вот что произойдет:'not-found' !== 'users'
- пропустить это.'users' === 'users'
- у нас есть матч.redirectTo: 'not-found'
, который применяется немедленно .not-found
.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, }, ], }, ];
'not-found' !== 'users'
- пропустить это.users
будет соответствовать первому сегменту URL-адреса, но конфигурация маршрута требуетfull
совпадения, поэтому пропустите его.'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 (
/
), вот как маршрутизатор решит это:welcome
не соответствует пустому сегменту, поэтому пропустите его.path: ''
соответствует пустому сегменту. У него естьpathMatch: 'full'
, что также удовлетворяет, поскольку мы сопоставили весь URL (у него был единственный пустой сегмент).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 немедленно останавливает это (из-за защиты, о которой я упоминал ранее), и все это работает нормально.источник
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?ignore my children
объяснение я придумал сам. Сомнение это как угловые разработчики видеть это, но это один из принциповpathMatch: 'full'
. Итак, в примере перенаправления, о котором вы говорите, обратите внимание, чтоpathMath: 'full'
он применяется ко второму маршруту (path: 'users'
), который из-за этого не соответствует. Соответствующий маршрут - этоpath: 'users/:userID'
, который не используетсяpathMatch: 'full'
и работает как обычно. Итак, сначала он совпадает,users/james
а затем мы ищемarticles
в его дочерних элементах (опять же, он не используетpathMatch: 'full'
).Стратегия сопоставления пути, одна из «префикс» или «полный». По умолчанию - «префикс».
По умолчанию маршрутизатор проверяет элементы URL-адреса слева, чтобы убедиться, что URL-адрес соответствует заданному пути, и останавливается при обнаружении совпадения. Например, '/ team / 11 / user' соответствует 'team /: id'.
Стратегия соответствия пути "полный" соответствует всему URL-адресу. Это важно сделать при перенаправлении маршрутов с пустым путем. В противном случае, поскольку пустой путь является префиксом любого URL-адреса, маршрутизатор будет применять перенаправление даже при переходе к месту назначения перенаправления, создавая бесконечный цикл.
Источник: https://angular.io/api/router/Route#properties
источник