Meskipun secara teknis benar, jawaban lain akan mendapat manfaat dari penjelasan tentang pencocokan URL-ke-rute Angular. Saya tidak berpikir Anda dapat sepenuhnya (memaafkan permainan kata-kata) memahami apa yang pathMatch: full
terjadi jika Anda tidak tahu cara kerja router di tempat pertama.
Mari kita definisikan beberapa hal dasar. Kami akan menggunakan URL ini sebagai contoh: /users/james/articles?from=134#section
.
Mungkin sudah jelas, tetapi pertama-tama mari kita tunjukkan bahwa parameter kueri ( ?from=134
) dan fragmen ( #section
) tidak memainkan peran apa pun dalam pencocokan jalur . Hanya url dasar ( /users/james/articles
) yang penting.
Angular membagi URL menjadi beberapa segmen . Segmen dari /users/james/articles
are, tentu saja users
, james
dan articles
.
Konfigurasi router adalah struktur pohon dengan simpul akar tunggal. Setiap Route
objek adalah node, yang mungkin memiliki children
node, yang pada gilirannya mungkin memiliki node lain children
atau node daun.
Tujuan dari perute adalah untuk menemukan cabang konfigurasi perute , dimulai dari simpul akar, yang akan cocok dengan semua (!!!) segmen dari URL. Ini penting! Jika Angular tidak menemukan cabang konfigurasi rute yang bisa cocok dengan seluruh URL - tidak lebih dan tidak kurang - itu tidak akan merender apapun .
Misalnya, jika URL target Anda adalah /a/b/c
tetapi router hanya dapat mencocokkan salah satu /a/b
atau /a/b/c/d
, maka tidak ada kecocokan dan aplikasi tidak akan merender apa pun.
Akhirnya, rute dengan redirectTo
berperilaku sedikit berbeda dari rute biasa, dan menurut saya rute tersebut akan menjadi satu-satunya tempat di mana orang benar-benar ingin menggunakannya pathMatch: full
. Tapi kita akan membahasnya nanti.
prefix
Pencocokan jalur default ( )
Alasan di balik nama tersebut prefix
adalah bahwa konfigurasi rute seperti itu akan memeriksa apakah yang dikonfigurasi path
adalah awalan dari segmen URL yang tersisa. Namun, router hanya dapat mencocokkan segmen penuh , yang membuat penamaan ini sedikit membingungkan.
Bagaimanapun, katakanlah ini adalah konfigurasi router level root kami:
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,
},
],
},
],
},
];
Perhatikan bahwa setiap Route
objek di sini menggunakan strategi pencocokan default, yaitu prefix
. Strategi ini berarti bahwa router melakukan iterasi ke seluruh pohon konfigurasi dan mencoba mencocokkannya dengan segmen URL target dengan segmen sampai URL benar - benar cocok . Begini cara melakukannya untuk contoh ini:
- Iterasi di atas larik root untuk mencari pencocokan tepat untuk segmen URL pertama -
users
.
'products' !== 'users'
, jadi lewati cabang itu. Perhatikan bahwa kami menggunakan pemeriksaan kesetaraan daripada .startsWith()
atau .includes()
- hanya pencocokan segmen penuh yang dihitung!
:other
cocok dengan nilai apa pun, jadi cocok. Namun, URL target belum sepenuhnya cocok (kami masih perlu mencocokkan james
dan articles
), sehingga router mencari turunan.
- Satu-satunya anak
:other
yaitu tricks
, yang !== 'james'
, maka tidak cocok.
- Angular kemudian menelusuri kembali ke array akar dan berlanjut dari sana.
'user' !== 'users
, lewati cabang.
'users' === 'users
- Segmennya cocok. Namun, ini belum full match, oleh karena itu kita perlu mencari anak-anak (sama seperti di langkah 3).
'permissions' !== 'james'
, Lewati.
:userID
cocok dengan apa pun, sehingga kami memiliki kecocokan untuk james
segmen tersebut. Namun ini masih belum full match, oleh karena itu kami perlu mencari anak yang mau cocok articles
.
- Kita bisa melihat yang
:userID
memiliki rute anak articles
, yang memberi kita pertandingan penuh! Dengan demikian aplikasi membuat UserArticlesComponent
.
full
Pencocokan URL lengkap ( )
Contoh 1
Bayangkan sekarang users
objek konfigurasi rute terlihat seperti ini:
{
path: 'users',
component: UsersComponent,
pathMatch: 'full',
children: [
{
path: 'permissions',
component: UsersPermissionsComponent,
},
{
path: ':userID',
component: UserComponent,
children: [
{
path: 'comments',
component: UserCommentsComponent,
},
{
path: 'articles',
component: UserArticlesComponent,
},
],
},
],
}
Perhatikan penggunaan pathMatch: full
. Jika ini masalahnya, langkah 1-5 akan sama, namun langkah 6 akan berbeda:
'users' !== 'users/james/articles
- segmen tidak cocok karena konfigurasi jalur users
dengan pathMatch: full
tidak cocok dengan URL lengkap, yaitu users/james/articles
.
- Karena tidak ada yang cocok, kami melewatkan cabang ini.
- Pada titik ini kami mencapai akhir konfigurasi router tanpa menemukan kecocokan. Aplikasi tidak memberikan apa pun .
Contoh 2
Bagaimana jika kita memiliki ini sebagai gantinya:
{
path: 'users/:userID',
component: UsersComponent,
pathMatch: 'full',
children: [
{
path: 'comments',
component: UserCommentsComponent,
},
{
path: 'articles',
component: UserArticlesComponent,
},
],
}
users/:userID
pathMatch: full
hanya dengan kecocokan users/james
sehingga tidak ada kecocokan sekali lagi, dan aplikasi tidak menampilkan apa pun.
Contoh 3
Mari pertimbangkan ini:
{
path: 'users',
children: [
{
path: 'permissions',
component: UsersPermissionsComponent,
},
{
path: ':userID',
component: UserComponent,
pathMatch: 'full',
children: [
{
path: 'comments',
component: UserCommentsComponent,
},
{
path: 'articles',
component: UserArticlesComponent,
},
],
},
],
}
Pada kasus ini:
'users' === 'users
- Segmennya cocok, tetapi james/articles
tetap tidak tertandingi. Ayo cari anak-anak.
'permissions' !== 'james'
- lewati.
:userID'
hanya dapat mencocokkan satu segmen, yaitu james
. Namun, ini adalah pathMatch: full
rute, dan harus cocok james/articles
(seluruh URL yang tersisa). Itu tidak dapat melakukan itu dan karenanya itu bukan pertandingan (jadi kami melewatkan cabang ini)!
- Sekali lagi, kami gagal menemukan kecocokan untuk URL dan aplikasi tidak membuat apa pun .
Seperti yang mungkin Anda perhatikan, pathMatch: full
konfigurasi pada dasarnya mengatakan ini:
Abaikan anak-anak saya dan hanya cocokkan saya. Jika saya tidak dapat mencocokkan sendiri semua segmen URL yang tersisa , lanjutkan.
Pengalihan
Semua Route
yang telah menetapkan a redirectTo
akan dicocokkan dengan URL target sesuai dengan prinsip yang sama. Satu-satunya perbedaan di sini adalah pengalihan diterapkan segera setelah segmen cocok . Artinya jika rute pengalihan menggunakan prefix
strategi default , kecocokan parsial sudah cukup untuk menyebabkan pengalihan . Inilah contoh yang bagus:
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,
},
],
},
];
Untuk URL awal kita ( /users/james/articles
), inilah yang akan terjadi:
'not-found' !== 'users'
- Lewati.
'users' === 'users'
- kita ada pertandingan.
- Pertandingan ini memiliki
redirectTo: 'not-found'
, yang segera diterapkan .
- URL target berubah menjadi
not-found
.
- Router mulai mencocokkan lagi dan langsung menemukan kecocokan
not-found
. Aplikasi membuat NotFoundComponent
.
Sekarang pertimbangkan apa yang akan terjadi jika users
rute tersebut juga memiliki 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'
- Lewati.
users
akan cocok dengan segmen pertama dari URL, tetapi konfigurasi rute membutuhkan full
kecocokan, jadi lewati saja.
'users/:userID'
korek api users/james
. articles
masih belum cocok tapi rute ini punya anak.
- Kami menemukan kecocokan untuk
articles
anak-anak. Seluruh URL sekarang cocok dan aplikasi ditampilkan UserArticlesComponent
.
Jalur kosong ( path: ''
)
Jalur kosong adalah kasus khusus karena dapat mencocokkan segmen apa pun tanpa "mengonsumsinya" (jadi turunannya harus mencocokkan segmen itu lagi). Pertimbangkan contoh ini:
const routes: Routes = [
{
path: '',
children: [
{
path: 'users',
component: BadUsersComponent,
}
]
},
{
path: 'users',
component: GoodUsersComponent,
},
];
Katakanlah kita mencoba mengakses /users
:
path: ''
akan selalu cocok, sehingga rutenya cocok. Namun, seluruh URL belum cocok - kami masih harus cocok users
!
- Kita dapat melihat bahwa ada anak
users
, yang cocok dengan segmen yang tersisa (dan hanya!) Dan kita memiliki kecocokan penuh. Aplikasi membuat BadUsersComponent
.
Sekarang kembali ke pertanyaan awal
OP menggunakan konfigurasi router ini:
const routes: Routes = [
{
path: 'welcome',
component: WelcomeComponent,
},
{
path: '',
redirectTo: 'welcome',
pathMatch: 'full',
},
{
path: '**',
redirectTo: 'welcome',
pathMatch: 'full',
},
];
Jika kita menavigasi ke root URL ( /
), berikut cara router menyelesaikannya:
welcome
tidak cocok dengan segmen kosong, jadi lewati saja.
path: ''
cocok dengan segmen kosong. Ini memiliki pathMatch: 'full'
, yang juga terpenuhi karena kami telah mencocokkan seluruh URL (memiliki satu segmen kosong).
- Pengalihan
welcome
terjadi dan aplikasi ditampilkan WelcomeComponent
.
Bagaimana jika tidak ada pathMatch: 'full'
?
Sebenarnya, orang akan berharap semuanya berperilaku persis sama. Namun, Angular secara eksplisit mencegah konfigurasi seperti itu ( { path: '', redirectTo: 'welcome' }
) karena jika Anda meletakkan ini di Route
atas welcome
, itu secara teoritis akan membuat loop pengalihan tanpa akhir. Jadi Angular hanya membuat kesalahan , itulah sebabnya aplikasi tidak berfungsi sama sekali! ( https://angular.io/api/router/Route#pathMatch )
Sebenarnya, ini tidak terlalu masuk akal bagi saya karena Angular juga telah menerapkan perlindungan terhadap pengalihan tanpa akhir seperti itu - ia hanya menjalankan satu pengalihan per tingkat perutean! Ini akan menghentikan semua pengalihan lebih lanjut (seperti yang akan Anda lihat pada contoh di bawah).
Tentang apa path: '**'
?
path: '**'
akan benar-benar cocok dengan apa pun ( af/frewf/321532152/fsa
adalah pertandingan) dengan atau tanpa pathMatch: 'full'
.
Juga, karena cocok dengan semuanya, jalur root juga disertakan, yang membuatnya { path: '', redirectTo: 'welcome' }
benar-benar mubazir dalam penyiapan ini.
Lucunya, tidak masalah untuk memiliki konfigurasi ini:
const routes: Routes = [
{
path: '**',
redirectTo: 'welcome'
},
{
path: 'welcome',
component: WelcomeComponent,
},
];
Jika kita menavigasi ke /welcome
, path: '**'
akan menjadi pertandingan dan pengalihan untuk menyambut akan terjadi. Secara teoritis ini harus memulai loop pengalihan tanpa akhir tetapi Angular segera menghentikannya (karena perlindungan yang saya sebutkan sebelumnya) dan semuanya berfungsi dengan baik.