Хоча технічно правильні, інші відповіді допомогли б пояснити відповідність 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/: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-адреса). Він не в змозі цього зробити, і, отже, це не збіг (тому ми пропускаємо цю гілку)!
- Знову ж таки, нам не вдалося знайти відповідність для 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 зупиняється це негайно, і все це працює нормально.