填寫這份《一分鐘調查》,幫我們(開發組)做得更好!去填寫Home

在單頁面應用中使用 Angular 路由

Using Angular routes in a single-page application

本課程將介紹如何建構一個使用多個 Angular 路由的單頁面應用 SPA。

This tutorial describes how you can build a single-page application, SPA that uses multiple Angular routes.

在 SPA 中,所有應用的所有功能都存在於同一個 HTML 頁面中。當用戶訪問應用的各種特性時,瀏覽器只需渲染那些使用者需要關心的部分,而不用重新載入頁面。這種模式可以顯著改善應用的使用者體驗。

In an SPA, all of your application's functions exist in a single HTML page. As users access your application's features, the browser needs to render only the parts that matter to the user, instead of loading a new page. This pattern can significantly improve your application's user experience.

為了定義使用者如何在應用中導航,你可以使用路由。你可以新增一些路由來定義使用者如何從應用的某個部分導航到另一部分。你也可以配置一些路由來防範意外或未經授權的行為。

To define how users navigate through your application, you use routes. You can add routes to define how users navigate from one part of your application to another. You can also configure routes to guard against unexpected or unauthorized behavior.

要探索本課程的範例應用,請參閱現場演練 / 下載範例

To explore a sample app featuring the contents of this tutorial, see the現場演練 / 下載範例.

目標

Objectives

  • 將範例應用的各個特性組織到一些模組中。

    Organize a sample application's features into modules.

  • 定義如何導航到元件。

    Define how to navigate to a component.

  • 使用引數把資訊傳給元件。

    Pass information to a component using a parameter.

  • 透過巢狀多個路由來構造路由體系。

    Structure routes by nesting several routes.

  • 檢查使用者是否可以訪問路由。

    Check whether users can access a route.

  • 控制該應用是否可以放棄未儲存的更改。

    Control whether the application can discard unsaved changes.

  • 透過預先獲取路由資料和延遲載入特性模組來提高效能。

    Improve performance by pre-fetching route data and lazy loading feature modules.

  • 需要特定的條件來載入元件。

    Require specific criteria to load components.

先決條件

Prerequisites

要完成本課程,你應該對這些概念有一個基本的瞭解:

To complete this tutorial, you should have a basic understanding of the following concepts:

你可能會發現英雄之旅課程很有幫助,但它並不是必須的。

You might find the Tour of Heroes tutorial helpful, but it is not required.

建立一個範例應用

Create a sample application

使用 Angular CLI,建立一個新的應用angular-router-sample。這個應用程式有兩個元件: crisis-listheroes-list

Using the Angular CLI, create a new application, angular-router-sample. This application will have two components: crisis-list and heroes-list.

  1. 建立一個新的 Angular 專案 angular-router-sample

    Create a new Angular project, angular-router-sample.

    ng new angular-router-sample
          
          ng new angular-router-sample
        

    當系統提示 Would you like to add Angular routing? 時,選擇 N

    When prompted with Would you like to add Angular routing?, select N.

    當系統提示 Which stylesheet format would you like to use? 時,選擇 CSS

    When prompted with Which stylesheet format would you like to use?, select CSS.

    一段時間後,一個新專案 angular-router-sample 就準備就緒了。

    After a few moments, a new project, angular-router-sample, is ready.

  2. 在終端上,導航到 angular-router-sample 目錄。

    From your terminal, navigate to the angular-router-sample directory.

  3. 建立一個元件 crisis-list

    Create a component, crisis-list.

    ng generate component crisis-list
          
          ng generate component crisis-list
        
  4. 在你的程式碼編輯器中,找到檔案 crisis-list.component.html 並用如下 HTML 替換佔位符內容。

    In your code editor, locate the file, crisis-list.component.html and replace the placeholder content with the following HTML.

    <h3>CRISIS CENTER</h3> <p>Get your crisis here</p>
    src/app/crisis-list/crisis-list.component.html
          
          <h3>CRISIS CENTER</h3>
    <p>Get your crisis here</p>
        
  5. 建立第二個元件 heroes-list

    Create a second component, heroes-list.

    ng generate component heroes-list
          
          ng generate component heroes-list
        
  6. 在你的程式碼編輯器中,找到 heroes-list.component.html 檔案,並用如下 HTML 替換佔位符內容。

    In your code editor, locate the file, heroes-list.component.html and replace the placeholder content with the following HTML.

    <h3>HEROES</h3> <p>Get your heroes here</p>
    src/app/heroes-list/heroes-list.component.html
          
          <h3>HEROES</h3>
    <p>Get your heroes here</p>
        
  7. 在你的程式碼編輯器中,開啟檔案 app.component.html 並用如下 HTML 替換其內容。

    In your code editor, open the file, app.component.html and replace its contents with the following HTML.

    <h1>Angular Router Sample</h1> <app-crisis-list></app-crisis-list> <app-heroes-list></app-heroes-list>
    src/app/app.component.html
          
          <h1>Angular Router Sample</h1>
    <app-crisis-list></app-crisis-list>
    <app-heroes-list></app-heroes-list>
        
  8. 執行 ng serve 來驗證新應用是否正常執行。

    Verify that your new application runs as expected by running the ng serve command.

    ng serve
          
          ng serve
        
  9. 開啟瀏覽器訪問 http://localhost:4200

    Open a browser to http://localhost:4200.

    你會看到一個網頁,它由一個標題和兩個元件的 HTML 組成。

    You should see a single web page, consisting of a title and the HTML of your two components.

@angular/router 匯入 RouterModule

Import RouterModule from @angular/router

路由允許你根據 URL 路徑顯示應用的特定檢視。要把這個功能新增到你的範例應用中,你需要更新 app.module.ts 檔案以使用模組 RouterModule。你可以從 @angular/router 匯入該模組。

Routing allows you to display specific views of your application depending on the URL path. To add this functionality to your sample application, you need to update the app.module.ts file to use the module, RouterModule. You import this module from @angular/router.

  1. 在程式碼編輯器中,開啟 app.module.ts 檔案。

    From your code editor, open the app.module.ts file.

  2. 新增如下 import 語句。

    Add the following import statement.

    import { RouterModule } from '@angular/router';
    src/app/app.module.ts
          
          import { RouterModule } from '@angular/router';
        

定義你的各個路由

Define your routes

在本節中,你將定義兩個路由:

In this section, you'll define two routes:

  • 路由 /crisis-center 用來開啟 crisis-center 元件。

    The route /crisis-center opens the crisis-center component.

  • 路由 /heroes-list 用來開啟 heroes-list 元件。

    The route /heroes-list opens the heroes-list component.

路由定義是一個 JavaScript 物件。每個路由通常都有兩個屬性。第一個屬性 path 是一個字串,它指定路由的 URL 路徑。第二個屬性 component 是元件類別,它指定應用要為該路由顯示哪個元件。

A route definition is a JavaScript object. Each route typically has two properties. The first property, path, is a string that specifies the URL path for the route. The second property, component, is a string that specifies what component your application should display for that path.

  1. 在程式碼編輯器中,開啟 app.module.ts 檔案。

    From your code editor, open the app.module.ts file.

  2. 找到 @NgModule() 部分。

    Locate the @NgModule() section.

  3. 用如下程式碼替換這部分的 imports 陣列。

    Replace the imports array in that section with the following.

    imports: [ BrowserModule, RouterModule.forRoot([ {path: 'crisis-list', component: CrisisListComponent}, {path: 'heroes-list', component: HeroesListComponent}, ]), ],
    src/app/app.module.ts
          
          imports: [
      BrowserModule,
      RouterModule.forRoot([
        {path: 'crisis-list', component: CrisisListComponent},
        {path: 'heroes-list', component: HeroesListComponent},
      ]),
    ],
        

這段程式碼把 RouterModule 新增到了 imports 陣列中。接下來,該程式碼使用 RouterModuleforRoot() 方法來定義你的兩個路由。該方法接受一個 JavaScript 物件陣列,每個物件定義一個路由的屬性。forRoot() 方法確保你的應用只會實例化一個 RouterModule。欲知詳情,請參閱單例服務

This code adds the RouterModule to the imports array. Next, the code uses the forRoot() method of the RouterModule to define your two routes. This method takes an array of JavaScript objects, with each object defining the proprties of a route. The forRoot() method ensures that your application only instantiates one RouterModule. For more information, see Singleton Services.

更新你的元件以新增 router-outlet

Update your component with router-outlet

此刻,你已經為應用定義了兩個路由。但是,你的應用仍然在你的 app.component.html 範本中硬編碼著 crisis-listheroes-list 元件。為了讓你的路由正常工作,需要更新範本,以便根據 URL 路徑動態載入一個元件。

At this point, you have defined two routes for your application. However, your application still has both the crisis-list and heroes-list components hard-coded in your app.component.html template. For your routes to work, you need to update your template to dynamically load a component based on the URL path.

要實現這個功能,你就可以把 router-outlet 指令新增到範本檔案中。

To implement this functionality, you add the router-outlet directive to your template file.

  1. 在程式碼編輯器中,開啟 app.component.html 檔案。

    From your code editor, open the app.component.html file.

  2. 刪除下面這幾行。

    Delete the following lines.

    <app-crisis-list></app-crisis-list> <app-heroes-list></app-heroes-list>
    src/app/app.component.html
          
          <app-crisis-list></app-crisis-list>
    <app-heroes-list></app-heroes-list>
        
  3. 新增 router-outlet 指令。

    Add the router-outlet directive.

    src/app/app.component.html
          
          <router-outlet></router-outlet>
        

在瀏覽器中檢視更新後的應用。你應該只看到應用標題。要檢視 crisis-list 元件,就要把 crisis-list 新增到瀏覽器位址列的路徑末尾。例如:

View your updated application in your browser. You should see only the application title. To view the crisis-list component, add crisis-list to the end of the path in your browser's address bar. For example:

http://localhost:4200/crisis-list
      
      http://localhost:4200/crisis-list
    

注意,crisis-list 元件會顯示出來。Angular 正在使用你定義的路由來動態載入元件。你可以用同樣的方法載入 heroes-list 元件:

Notice that the crisis-list component displays. Angular is using the route you defined to dynamically load the component. You can load the heroes-list component the same way:

http://localhost:4200/heroes-list
      
      http://localhost:4200/heroes-list
    

用 UI 元素控制導航

Control navigation with UI elements

目前,你的應用支援兩種路由。但是目前使用這些路由的唯一方法是讓使用者在瀏覽器的位址列中手動輸入路徑。在本節中,你要新增兩個連結,使用者可以單擊它們在 heroes-listcrisis-list 元件之間導航。你還會新增一些 CSS 樣式。雖然這些樣式不是必需的,但它們可以讓你更容易的識別出當前顯示的元件的連結。你將在下一節中新增此功能。

Currently, your application supports two routes. However, the only way to use those routes is for the user to manually type the path in the browser's address bar. In this section, you'll add two links that users can click to navigate between the heroes-list and crisis-list components. You'll also add some CSS styles. While these styles are not required, they make it easier to identify the link for the currently-displayed component. You'll add that functionality in the next section.

  1. 開啟 app.component.html 檔案,在標題下方新增以下 HTML。

    Open the app.component.html file and add the following HTML below the title.

    <nav> <a class="button" routerLink="/crisis-list">Crisis Center</a> | <a class="button" routerLink="/heroes-list">Heroes</a> </nav>
    src/app/app.component.html
          
          <nav>
      <a class="button" routerLink="/crisis-list">Crisis Center</a> |
      <a class="button" routerLink="/heroes-list">Heroes</a>
    </nav>
        

    這個 HTML 使用了 Angular 指令 routerLink。該指令將你定義的路由連線到範本檔案中。

    This HTML uses an Angular directive, routerLink. This directive connects the routes you defined to your template files.

  2. 開啟 app.component.css 檔案並新增如下樣式。

    Open the app.component.css file and add the following styles.

    .button { box-shadow: inset 0px 1px 0px 0px #ffffff; background: linear-gradient(to bottom, #ffffff 5%, #f6f6f6 100%); background-color: #ffffff; border-radius: 6px; border: 1px solid #dcdcdc; display: inline-block; cursor: pointer; color: #666666; font-family: Arial; font-size: 15px; font-weight: bold; padding: 6px 24px; text-decoration: none; text-shadow: 0px 1px 0px #ffffff; outline: 0; } .activebutton { box-shadow: inset 0px 1px 0px 0px #dcecfb; background: linear-gradient(to bottom, #bddbfa 5%, #80b5ea 100%); background-color: #bddbfa; border-radius: 6px; border: 1px solid #84bbf3; display: inline-block; cursor: pointer; color: #ffffff; font-family: Arial; font-size: 15px; font-weight: bold; padding: 6px 24px; text-decoration: none; text-shadow: 0px 1px 0px #528ecc; outline: 0; }
    src/app/app.component.css
          
          .button {
        box-shadow: inset 0px 1px 0px 0px #ffffff;
        background: linear-gradient(to bottom, #ffffff 5%, #f6f6f6 100%);
        background-color: #ffffff;
        border-radius: 6px;
        border: 1px solid #dcdcdc;
        display: inline-block;
        cursor: pointer;
        color: #666666;
        font-family: Arial;
        font-size: 15px;
        font-weight: bold;
        padding: 6px 24px;
        text-decoration: none;
        text-shadow: 0px 1px 0px #ffffff;
        outline: 0;
    }
    .activebutton {
        box-shadow: inset 0px 1px 0px 0px #dcecfb;
        background: linear-gradient(to bottom, #bddbfa 5%, #80b5ea 100%);
        background-color: #bddbfa;
        border-radius: 6px;
        border: 1px solid #84bbf3;
        display: inline-block;
        cursor: pointer;
        color: #ffffff;
        font-family: Arial;
        font-size: 15px;
        font-weight: bold;
        padding: 6px 24px;
        text-decoration: none;
        text-shadow: 0px 1px 0px #528ecc;
        outline: 0;
    }
        

如果你在瀏覽器中檢視應用,你會看到這兩個連結。單擊某個連結時,會出現相應的元件。

If you view your application in the browser, you should see these two links. When you click on a link, the corresponding component appears.

標出活動路由

Identify the active route

雖然使用者可以使用上一節中新增的連結來瀏覽你的應用,但他們並沒有簡單的方法來確定活動路由是什麼。可以使用 Angular 的 routerLinkActive 指令新增這個功能。

While users can navigate your application using the links you added in the previous section, they don't have an easy way to identify what the active route is. You can add this functionality using Angular's routerLinkActive directive.

  1. 在程式碼編輯器中,開啟 app.component.html 檔案。

    From your code editor, open the app.component.html file.

  2. 更新 a 標籤以包含 routerLinkActive 指令。

    Update the anchor tags to include the routerLinkActive directive.

    <nav> <a class="button" routerLink="/crisis-list" routerLinkActive="activebutton">Crisis Center</a> | <a class="button" routerLink="/heroes-list" routerLinkActive="activebutton">Heroes</a> </nav>
    src/app/app.component.html
          
          <nav>
      <a class="button" routerLink="/crisis-list" routerLinkActive="activebutton">Crisis Center</a> |
      <a class="button" routerLink="/heroes-list" routerLinkActive="activebutton">Heroes</a>
    </nav>
        

再次檢視你的申請表。單擊其中一個按鈕時,該按鈕的樣式會自動更新,並為該使用者標出該活動元件。透過新增 routerLinkActive 指令,可以通知你的應用把一個特定的 CSS 類別應用到當前的活動路由中。在本課程中,這個 CSS 類別是 activebutton,但你可以使用任何想要的類別。

View your application again. As you click one of the buttons, the style for that button updates automatically, identifying the active component to the user. By adding the routerLinkActive directive, you inform your application to apply a specific CSS class to the active route. In this tutorial, that CSS class is activebutton, but you could use any class that you want.

新增一個重新導向

Adding a redirect

在本課程的這一步中,你將新增一個重新導向路由來把使用者導向 /heroes-list 元件。

In this step of the tutorial, you add a route that redirects the user to display the /heroes-list component.

  1. 在程式碼編輯器中,開啟 app.module.ts 檔案。

    From your code editor, open the app.module.ts file.

  2. imports 陣列中,按如下所示更新 RouterModule 部分。

    In the imports array, update the RouterModule section as follows.

    imports: [ BrowserModule, RouterModule.forRoot([ {path: 'crisis-list', component: CrisisListComponent}, {path: 'heroes-list', component: HeroesListComponent}, {path: '', redirectTo: '/heroes-list', pathMatch: 'full'}, ]), ],
    src/app/app.module.ts
          
          imports: [
      BrowserModule,
      RouterModule.forRoot([
        {path: 'crisis-list', component: CrisisListComponent},
        {path: 'heroes-list', component: HeroesListComponent},
        {path: '', redirectTo: '/heroes-list', pathMatch: 'full'},
      ]),
    ],
        

    注意這個新路由使用一個空字串作為它的路徑。另外,它還把 component 屬性替換成了這兩個新屬性:

    Notice that this new route uses an empty string as its path. In addition, it replaces the component property with two new ones:

    • redirectTo。這個屬性指示 Angular 從空路徑重新導向到 heroes-list 路徑。

      redirectTo. This property instructs Angular to redirect from an empty path to the heroes-list path.

    • pathMatch。這個屬性指示 Angular 要如何匹配 URL。對於本課程,你應該把這個屬性設定為 full。當路徑為空字串時,建議使用此策略。關於此屬性的更多資訊,請參閱 Route API 文件

      pathMatch. This property instructs Angular on how much of the URL to match. For this tutorial, you should set this property to full. This strategy is recommended when you have an empty string for a path. For more information about this property, see the Route API documentation.

現在,當你開啟應用時,它會預設顯示 heroes-list 元件。

Now when you open your application, it displays the heroes-list component by default.

新增 404 頁面

Adding a 404 page

使用者可以嘗試訪問你尚未定義的路由。為了解決這個問題,最佳做法是顯示一個 404 頁面。在本節中,你將建立一個 404 頁面,並更新路由配置,以便為任何未指定的路由顯示該頁面。

It is possible for a user to try to access a route that you have not defined. To account for this behavior, the best practice is to display a 404 page. In this section, you'll create a 404 page and update your route configuration to show that page for any unspecified routes.

  1. 在終端上,建立一個新的元件 PageNotFound

    From the terminal, create a new component, PageNotFound.

    ng generate component page-not-found
          
          ng generate component page-not-found
        
  2. 在程式碼編輯器中,開啟 page-not-found.component.html 檔案並用下面的 HTML 替換它的內容。

    From your code editor, open the page-not-found.component.html file and replace its contents with the following HTML.

    <h2>Page Not Found</h2> <p>We couldn't find that page! Not even with x-ray vision.</p>
    src/app/page-not-found/page-not-found.component.html
          
          <h2>Page Not Found</h2>
    <p>We couldn't find that page! Not even with x-ray vision.</p>
        
  3. 開啟 app.module.ts 檔案。在其 imports 陣列中,按如下所示更新 RouterModule 部分的內容。

    Open the app.module.ts file. In the imports array, update the RouterModule section as follows.

    imports: [ BrowserModule, RouterModule.forRoot([ {path: 'crisis-list', component: CrisisListComponent}, {path: 'heroes-list', component: HeroesListComponent}, {path: '', redirectTo: '/heroes-list', pathMatch: 'full'}, {path: '**', component: PageNotFoundComponent} ]), ],
    src/app/app.module.ts
          
          imports: [
      BrowserModule,
      RouterModule.forRoot([
        {path: 'crisis-list', component: CrisisListComponent},
        {path: 'heroes-list', component: HeroesListComponent},
        {path: '', redirectTo: '/heroes-list', pathMatch: 'full'},
        {path: '**', component: PageNotFoundComponent}
      ]),
    ],
        

    新路由使用路徑 **。這個路徑是 Angular 表示萬用字元路由的方式。任何與你配置中的路由都不匹配的路由都會使用這個路由。

    The new route uses a path, **. This path is how Angular identifies a wildcard route. Any route that does not match an existing route in your configuration will use this route.

    請注意,萬用字元路由要放在陣列的末尾。路由的順序很重要,因為 Angular 會按順序應用路由並使用所找到的第一個匹配項。

    Notice that the wildcard route is placed at the end of the array. The order of your routes is important, as Angular applies routes in order and uses the first match it finds.

嘗試導航到應用中不存在的路由,比如 http://localhost:4200/powers。此路由與 app.module.ts 檔案中定義的所有內容都不匹配。但是,由於你定義了一個萬用字元路由,該應用會自動顯示你的 PageNotFound 元件。

Try navigating to a non-existing route on your application, such as http://localhost:4200/powers. This route doesn't match anything defined in your app.module.ts file. However, because you defined a wildcard route, the application automatically displays your PageNotFound component.

下一步

Next steps

你已經有了一個基本的應用程式,它使用 Angular 的路由功能來根據 URL 地址改變使用者可以看到的元件。你還擴充套件了這些特性,以包含一個重新導向,以及一個用來顯示自訂 404 頁面的萬用字元路由。

At this point, you have a basic application that uses Angular's routing feature to change what components the user can see based on the URL address. You have extended these features to include a redirect, as well as a wildcard route to display a custom 404 page.

關於路由的更多資訊,請參閱以下主題:

For more information about routing, see the following topics: