Хоча технічно правильні, інші відповіді допомогли б пояснити відповідність 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-адреси. Це надзвичайно важливо! Якщо не Кутовий годі й шукати конфігурації маршруту гілки , яка може відповідати всьому 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-адреса не буде повністю збігатися . Ось як це можна зробити для цього прикладу:
- Перебирайте кореневий масив, шукаючи точну відповідність для першого сегмента URL -
users.
'products' !== 'users', тому пропустіть цю гілку. Зверніть увагу, що ми використовуємо перевірку на рівність, а не - .startsWith()або .includes()лише - збіги повного сегмента!
:otherвідповідає будь-якому значенню, тому це збіг. Однак цільова URL-адреса ще не повністю узгоджена (нам все одно потрібно збігатись jamesі articles), тому маршрутизатор шукає дітей.
- Єдина дитина
:otherє tricks, що є !== 'james', отже, не збігом.
- Потім Angular повертається назад до кореневого масиву і продовжує звідти.
'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/: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,
},
],
},
],
}
В цьому випадку:
'users' === 'users- сегмент відповідає, але james/articlesвсе ще залишається неперевершеним. Давайте шукати дітей.
'permissions' !== 'james' - пропустити.
:userID'може відповідати лише одному сегменту, що було б james. Однак це pathMatch: fullмаршрут, і він повинен збігатися james/articles(вся залишилася URL-адреса). Він не в змозі цього зробити, і, отже, це не збіг (тому ми пропускаємо цю гілку)!
- Знову ж таки, нам не вдалося знайти відповідність для 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) ось що трапиться:
'not-found' !== 'users' - пропустити це.
'users' === 'users' - у нас сірник.
- Цей збіг має a
redirectTo: 'not-found', який застосовується негайно .
- Цільова URL-адреса змінюється на
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: ''відповідає порожньому сегменту. Він має a 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: '**'буде матч і відбудеться переадресація на привітання. Це повинно розпочати нескінченний цикл переспрямувань, але Angular зупиняється це негайно, і все це працює нормально.