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