ในขณะที่ถูกต้องในทางเทคนิคคำตอบอื่น ๆ จะได้รับประโยชน์จากคำอธิบายของการจับคู่ URL กับเส้นทางของ Angular ฉันไม่คิดว่าคุณจะสามารถ (ให้อภัยการเล่นสำนวน) ได้อย่างเต็มที่เข้าใจว่าpathMatch: full
จะทำอย่างไรถ้าคุณไม่รู้ว่าเราเตอร์ทำงานอย่างไรตั้งแต่แรก
ก่อนอื่นให้กำหนดสิ่งพื้นฐานบางประการ เราจะใช้ URL นี้เป็นตัวอย่าง: /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
กลยุทธ์นี้หมายถึงว่าเราเตอร์ iterates กว่าต้นการตั้งค่าทั้งหมดและพยายามที่จะจับคู่กับ 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
ดังนั้นการประยุกต์ใช้วาทกรรม
การfull
จับคู่URL แบบเต็ม ( )
ตัวอย่าง 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
ที่กำหนดไว้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'
ซึ่งจะนำไปใช้ทันที
- การเปลี่ยนแปลง 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 จะหยุดทันที (เนื่องจากการป้องกันที่ฉันพูดถึงก่อนหน้านี้) และสิ่งทั้งหมดก็ใช้ได้ดี