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

常見路由任務

Common Routing Tasks

本主題講述當把 Angular 路由器新增到應用中時,如何實現多種常見路由任務。

This topic describes how to implement many of the common tasks associated with adding the Angular router to your application.

產生一個支援路由的應用

Generate an app with routing enabled

下面的命令會用 Angular CLI 來產生一個帶有應用路由模組(AppRoutingModule)的基本 Angular 應用,它是一個 NgModule,可用來配置路由。下面的例子中應用的名字是 routing-app

The following command uses the Angular CLI to generate a basic Angular app with an app routing module, called AppRoutingModule, which is an NgModule where you can configure your routes. The app name in the following example is routing-app.

      
      ng new routing-app --routing
    

一旦產生新應用,CLI 就會提示你選擇 CSS 或 CSS 前處理器。在這個例子中,我們接受 CSS 的預設值。

When generating a new app, the CLI prompts you to select CSS or a CSS preprocessor. For this example, accept the default of CSS.

為路由新增元件

Adding components for routing

為了使用 Angular 的路由器,應用至少要有兩個元件才能從一個導航到另一個。要使用 CLI 建立元件,請在命令列輸入以下內容,其中 first 是元件的名稱:

To use the Angular router, an app needs to have at least two components so that it can navigate from one to the other. To create a component using the CLI, enter the following at the command line where first is the name of your component:

      
      ng generate component first
    

為第二個元件重複這個步驟,但給它一個不同的名字。這裡的新名字是 second

Repeat this step for a second component but give it a different name. Here, the new name is second.

      
      ng generate component second
    

CLI 會自動新增 Component 字尾,所以如果在編寫 first-component,那麼其元件名就是 FirstComponentComponent

The CLI automatically appends Component, so if you were to write first-component, your component would be FirstComponentComponent.

<base href>

本指南適用於 CLI 產生的 Angular 應用。如果你是手動工作的,請確保你的 index.html 檔案的 <head> 中有 <base href="/"> 語句。這裡假定 app 資料夾是應用的根目錄,並使用 "/" 作為基礎路徑。

This guide works with a CLI-generated Angular app. If you are working manually, make sure that you have <base href="/"> in the <head> of your index.html file. This assumes that the app folder is the application root, and uses "/".

匯入這些新元件

Importing your new components

要使用這些新元件,請把它們匯入到該檔案頂部的 AppRoutingModule 中,具體如下:

To use your new components, import them into AppRoutingModule at the top of the file, as follows:

AppRoutingModule (excerpt)
      
      import { FirstComponent } from './first/first.component';
import { SecondComponent } from './second/second.component';
    

定義一個基本路由

Defining a basic route

建立路由有三個基本的建構塊。

There are three fundamental building blocks to creating a route.

AppRoutingModule 匯入 AppModule 並把它新增到 imports 陣列中。

Import the AppRoutingModule into AppModule and add it to the imports array.

Angular CLI 會為你執行這一步驟。但是,如果要手動建立應用或使用現存的非 CLI 應用,請驗證匯入和配置是否正確。下面是使用 --routing 標誌產生的預設 AppModule

The Angular CLI performs this step for you. However, if you are creating an app manually or working with an existing, non-CLI app, verify that the imports and configuration are correct. The following is the default AppModule using the CLI with the --routing flag.

Default CLI AppModule with routing
      
      import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module'; // CLI imports AppRoutingModule
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule // CLI adds AppRoutingModule to the AppModule's imports array
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
    
  1. RouterModuleRoutes 匯入到你的路由模組中。

    Import RouterModule and Routes into your routing module.

    Angular CLI 會自動執行這一步驟。CLI 還為你的路由設定了 Routes 陣列,並為 @NgModule() 配置了 importsexports 陣列。

    The Angular CLI performs this step automatically. The CLI also sets up a Routes array for your routes and configures the imports and exports arrays for @NgModule().

    CLI app routing module
          
          import { NgModule } from '@angular/core';
    import { Routes, RouterModule } from '@angular/router'; // CLI imports router
    
    const routes: Routes = []; // sets up routes constant where you define your routes
    
    // configures NgModule imports and exports
    @NgModule({
      imports: [RouterModule.forRoot(routes)],
      exports: [RouterModule]
    })
    export class AppRoutingModule { }
        
  2. Routes 陣列中定義你的路由。

    Define your routes in your Routes array.

    這個陣列中的每個路由都是一個包含兩個屬性的 JavaScript 物件。第一個屬性 path 定義了該路由的 URL 路徑。第二個屬性 component 定義了要讓 Angular 用作相應路徑的元件。

    Each route in this array is a JavaScript object that contains two properties. The first property, path, defines the URL path for the route. The second property, component, defines the component Angular should use for the corresponding path.

AppRoutingModule (excerpt)
      
      const routes: Routes = [
  { path: 'first-component', component: FirstComponent },
  { path: 'second-component', component: SecondComponent },
];
    
  1. 把這些路由新增到你的應用中。

    Add your routes to your application.

    現在你已經定義了路由,可以把它們新增到應用中了。首先,新增到這兩個元件的連結。把要新增路由的連結賦值給 routerLink 屬性。將屬性的值設定為該元件,以便在使用者點選各個連結時顯示這個值。接下來,修改元件範本以包含 <router-outlet> 標籤。該元素會通知 Angular,你可以用所選路由的元件更新應用的檢視。

    Now that you have defined your routes, you can add them to your application. First, add links to the two components. Assign the anchor tag that you want to add the route to the routerLink attribute. Set the value of the attribute to the component to show when a user clicks on each link. Next, update your component template to include <router-outlet>. This element informs Angular to update the application view with the component for the selected route.

    Template with routerLink and router-outlet
          
          <h1>Angular Router App</h1>
    <!-- This nav gives you links to click, which tells the router which route to use (defined in the routes constant in  AppRoutingModule) -->
    <nav>
      <ul>
        <li><a routerLink="/first-component" routerLinkActive="active">First Component</a></li>
        <li><a routerLink="/second-component" routerLinkActive="active">Second Component</a></li>
      </ul>
    </nav>
    <!-- The routed views render in the <router-outlet>-->
    <router-outlet></router-outlet>
        

路由順序

Route order

路由的順序很重要,因為 Router 在匹配路由時使用“先到先得”策略,所以應該在不那麼具體的路由前面放置更具體的路由。首先列出靜態路徑的路由,然後是一個與預設路由匹配的空路徑路由。萬用字元路由是最後一個,因為它匹配每一個 URL,只有當其它路由都沒有匹配時,Router 才會選擇它。

The order of routes is important because the Router uses a first-match wins strategy when matching routes, so more specific routes should be placed above less specific routes. List routes with a static path first, followed by an empty path route, which matches the default route. The wildcard route comes last because it matches every URL and the Router selects it only if no other routes match first.

獲取路由資訊

Getting route information

通常,當用戶導航你的應用時,你會希望把資訊從一個元件傳遞到另一個元件。例如,考慮一個顯示雜貨商品購物清單的應用。列表中的每一項都有一個唯一的 id。要想編輯某個專案,使用者需要單擊“編輯”按鈕,開啟一個 EditGroceryItem 元件。你希望該元件得到該商品的 id,以便它能向用戶顯示正確的資訊。

Often, as a user navigates your application, you want to pass information from one component to another. For example, consider an application that displays a shopping list of grocery items. Each item in the list has a unique id. To edit an item, users click an Edit button, which opens an EditGroceryItem component. You want that component to retrieve the id for the grocery item so it can display the right information to the user.

你也可以使用一個路由把這種型別的資訊傳給你的應用元件。要做到這一點,你可以使用 ActivatedRoute 介面。

You can use a route to pass this type of information to your application components. To do so, you use the ActivatedRoute interface.

要從路由中獲取資訊:

To get information from a route:

  1. ActivatedRouteParamMap 匯入你的元件。

    Import ActivatedRoute and ParamMap to your component.

    In the component class (excerpt)
          
          import { Router, ActivatedRoute, ParamMap } from '@angular/router';
        

    這些 import 語句添加了元件所需的幾個重要元素。要詳細瞭解每個 API,請參閱以下 API 頁面:

    These import statements add several important elements that your component needs. To learn more about each, see the following API pages:

  2. 透過把 ActivatedRoute 的一個實例新增到你的應用的建構函式中來注入它:

    Inject an instance of ActivatedRoute by adding it to your application's constructor:

    In the component class (excerpt)
          
          constructor(
      private route: ActivatedRoute,
    ) {}
        
  3. 更新 ngOnInit() 方法來訪問這個 ActivatedRoute 並追蹤 id 引數:

    Update the ngOnInit() method to access the ActivatedRoute and track the id parameter:

    In the component (excerpt)
          
          ngOnInit() {
      this.route.queryParams.subscribe(params => {
        this.name = params['name'];
      });
    }
        

    注意:前面的例子使用了一個變數 name,並根據 name 引數給它賦值。

    Note: The preceding example uses a variable, name, and assigns it the value based on the name parameter.

設定萬用字元路由

Setting up wildcard routes

當用戶試圖導航到那些不存在的應用部件時,在正常的應用中應該能得到很好的處理。要在應用中新增此功能,需要設定萬用字元路由。當所請求的 URL 與任何路由器路徑都不匹配時,Angular 路由器就會選擇這個路由。

A well-functioning application should gracefully handle when users attempt to navigate to a part of your application that does not exist. To add this functionality to your application, you set up a wildcard route. The Angular router selects this route any time the requested URL doesn't match any router paths.

要設定萬用字元路由,請在 routes 定義中新增以下程式碼。

To set up a wildcard route, add the following code to your routes definition.

AppRoutingModule (excerpt)
      
      { path: '**', component:  }

    

這兩個星號 ** 告訴 Angular,這個 routes 定義是萬用字元路由。對於 component 屬性,你可以使用應用中的任何元件。常見的選擇包括應用專屬的 PageNotFoundComponent,你可以定義它來向用戶展示 404 頁面,或者跳轉到應用的主元件。萬用字元路由是最後一個路由,因為它匹配所有的 URL。關於路由順序的更多詳細資訊,請參閱路由順序

The two asterisks, **, indicate to Angular that this routes definition is a wildcard route. For the component property, you can define any component in your application. Common choices include an application-specific PageNotFoundComponent, which you can define to display a 404 page to your users; or a redirect to your application's main component. A wildcard route is the last route because it matches any URL. For more detail on why order matters for routes, see Route order.

顯示 404 頁面

Displaying a 404 page

要顯示 404 頁面,請設定一個萬用字元路由,並將 component 屬性設定為你要用於 404 頁面的元件,如下所示:

To display a 404 page, set up a wildcard route with the component property set to the component you'd like to use for your 404 page as follows:

AppRoutingModule (excerpt)
      
      const routes: Routes = [
  { path: 'first-component', component: FirstComponent },
  { path: 'second-component', component: SecondComponent },
  { path: '**', component: PageNotFoundComponent },  // Wildcard route for a 404 page
];
    

path** 的最後一條路由是萬用字元路由。如果請求的 URL 與前面列出的路徑不匹配,路由器會選擇這個路由,並把該使用者送到 PageNotFoundComponent

The last route with the path of ** is a wildcard route. The router selects this route if the requested URL doesn't match any of the paths earlier in the list and sends the user to the PageNotFoundComponent.

設定重新導向

Setting up redirects

要設定重新導向,請使用重新導向源的 path、要重新導向目標的 component 和一個 pathMatch 值來配置路由,以告訴路由器該如何匹配 URL。

To set up a redirect, configure a route with the path you want to redirect from, the component you want to redirect to, and a pathMatch value that tells the router how to match the URL.

AppRoutingModule (excerpt)
      
      const routes: Routes = [
  { path: 'first-component', component: FirstComponent },
  { path: 'second-component', component: SecondComponent },
  { path: '',   redirectTo: '/first-component', pathMatch: 'full' }, // redirect to `first-component`
  { path: '**', component: PageNotFoundComponent },  // Wildcard route for a 404 page
];
    

在這個例子中,第三個路由是重新導向路由,所以路由器會預設跳到 first-component 路由。注意,這個重新導向路由位於萬用字元路由之前。這裡的 path: '' 表示使用初始的相對 URL( '' )。

In this example, the third route is a redirect so that the router defaults to the first-component route. Notice that this redirect precedes the wildcard route. Here, path: '' means to use the initial relative URL ('').

關於 pathMatch 的詳情,請參閱聚焦 pathMatch部分。

For more details on pathMatch see Spotlight on pathMatch.

巢狀路由

Nesting routes

隨著你的應用變得越來越複雜,你可能要建立一些根元件之外的相對路由。這些巢狀路由型別稱為子路由。這意味著你要為你的應用新增第二 <router-outlet>,因為它是 AppComponent 之外的另一個 <router-outlet>

As your application grows more complex, you may want to create routes that are relative to a component other than your root component. These types of nested routes are called child routes. This means you're adding a second <router-outlet> to your app, because it is in addition to the <router-outlet> in AppComponent.

在這個例子中,還有兩個子元件,child-achild-b。這裡的 FirstComponent 有它自己的 <nav>AppComponent 之外的第二 <router-outlet>

In this example, there are two additional child components, child-a, and child-b. Here, FirstComponent has its own <nav> and a second <router-outlet> in addition to the one in AppComponent.

In the template
      
      <h2>First Component</h2>

<nav>
  <ul>
    <li><a routerLink="child-a">Child A</a></li>
    <li><a routerLink="child-b">Child B</a></li>
  </ul>
</nav>

<router-outlet></router-outlet>
    

子路由和其它路由一樣,同時需要 pathcomponent。唯一的區別是你要把子路由放在父路由的 children 陣列中。

A child route is like any other route, in that it needs both a path and a component. The one difference is that you place child routes in a children array within the parent route.

AppRoutingModule (excerpt)
      
      const routes: Routes = [
  {
    path: 'first-component',
    component: FirstComponent, // this is the component with the <router-outlet> in the template
    children: [
      {
        path: 'child-a', // child route path
        component: ChildAComponent, // child route component that the router renders
      },
      {
        path: 'child-b',
        component: ChildBComponent, // another child route component that the router renders
      },
    ],
  },
];
    

使用相對路徑

Using relative paths

相對路徑允許你定義相對於當前 URL 段的路徑。下面的例子展示了到另一個元件 second-component 的相對路由。FirstComponentSecondComponent 在樹中處於同一級別,但是,指向 SecondComponent 的連結位於 FirstComponent 中,這意味著路由器必須先上升一個級別,然後進入二級目錄才能找到 SecondComponent。你可以使用 ../ 符號來上升一個級別,而不用寫出到 SecondComponent 的完整路徑。

Relative paths allow you to define paths that are relative to the current URL segment. The following example shows a relative route to another component, second-component. FirstComponent and SecondComponent are at the same level in the tree, however, the link to SecondComponent is situated within the FirstComponent, meaning that the router has to go up a level and then into the second directory to find the SecondComponent. Rather than writing out the whole path to get to SecondComponent, you can use the ../ notation to go up a level.

In the template
      
      <h2>First Component</h2>

<nav>
  <ul>
    <li><a routerLink="../second-component">Relative Route to second component</a></li>
  </ul>
</nav>
<router-outlet></router-outlet>
    

除了 ../,還可以使用 ./ 或者不帶前導斜槓來指定當前級別。

In addition to ../, you can use ./ or no leading slash to specify the current level.

指定相對路由

Specifying a relative route

要指定相對路由,請使用 NavigationExtras 中的 relativeTo 屬性。在元件類別中,從 @angular/router 匯入 NavigationExtras

To specify a relative route, use the NavigationExtras relativeTo property. In the component class, import NavigationExtras from the @angular/router.

然後在導航方法中使用 relativeTo 引數。在連結引數陣列(它包含 items)之後新增一個物件,把該物件的 relativeTo 屬性設定為當前的 ActivatedRoute,也就是 this.route

Then use relativeTo in your navigation method. After the link parameters array, which here contains items, add an object with the relativeTo property set to the ActivatedRoute, which is this.route.

RelativeTo
      
      goToItems() {
  this.router.navigate(['items'], { relativeTo: this.route });
}
    

goToItems() 方法會把目標 URI 解釋為相對於當前路由的,並導航到 items 路由。

The goToItems() method interprets the destination URI as relative to the activated route and navigates to the items route.

訪問查詢引數和片段

Accessing query parameters and fragments

有時,應用中的某個特性需要訪問路由的部件,比如查詢引數或片段(fragment)。本課程的這個階段使用了一個“英雄之旅”中的列表檢視,你可以在其中點選一個英雄來檢視詳情。路由器使用 id 來顯示正確的英雄的詳情。

Sometimes, a feature of your application requires accessing a part of a route, such as a query parameter or a fragment. The Tour of Heroes app at this stage in the tutorial uses a list view in which you can click on a hero to see details. The router uses an id to show the correct hero's details.

首先,在要導航的元件中匯入以下成員。

First, import the following members in the component you want to navigate from.

Component import statements (excerpt)
      
      import { ActivatedRoute } from '@angular/router';
import { Observable } from 'rxjs';
import { switchMap } from 'rxjs/operators';
    

接下來,注入當前路由(ActivatedRoute)服務:

Next inject the activated route service:

Component (excerpt)
      
      constructor(private route: ActivatedRoute) {}
    

配置這個類別,讓你有一個可觀察物件 heroes$、一個用來儲存英雄的 id 號的 selectedId,以及 ngOnInit() 中的英雄們,新增下面的程式碼來獲取所選英雄的 id。這個程式碼片段假設你有一個英雄列表、一個英雄服務、一個能獲取你的英雄的函式,以及用來渲染你的列表和細節的 HTML,就像在《英雄之旅》例子中一樣。

Configure the class so that you have an observable, heroes$, a selectedId to hold the id number of the hero, and the heroes in the ngOnInit(), add the following code to get the id of the selected hero. This code snippet assumes that you have a heroes list, a hero service, a function to get your heroes, and the HTML to render your list and details, just as in the Tour of Heroes example.

Component 1 (excerpt)
      
      heroes$: Observable;
selectedId: number;
heroes = HEROES;

ngOnInit() {
  this.heroes$ = this.route.paramMap.pipe(
    switchMap(params => {
      this.selectedId = Number(params.get('id'));
      return this.service.getHeroes();
    })
  );
}

    

接下來,在要導航到的元件中,匯入以下成員。

Next, in the component that you want to navigate to, import the following members.

Component 2 (excerpt)
      
      import { Router, ActivatedRoute, ParamMap } from '@angular/router';
import { Observable } from 'rxjs';
    

在元件類別的建構函式中注入 ActivatedRouteRouter,這樣在這個元件中就可以用它們了:

Inject ActivatedRoute and Router in the constructor of the component class so they are available to this component:

Component 2 (excerpt)
      
      hero$: Observable;

  constructor(
    private route: ActivatedRoute,
    private router: Router  ) {}

  ngOnInit() {
    const heroId = this.route.snapshot.paramMap.get('id');
    this.hero$ = this.service.getHero(heroId);
  }

  gotoItems(hero: Hero) {
    const heroId = hero ? hero.id : null;
    // Pass along the hero id if available
    // so that the HeroList component can select that item.
    this.router.navigate(['/heroes', { id: heroId }]);
  }

    

延遲載入

Lazy loading

你可以配置路由定義來實現延遲載入模組,這意味著 Angular 只會在需要時才載入這些模組,而不是在應用啟動時就載入全部。 另外,你可以在後臺預載入一些應用部件來改善使用者體驗。

You can configure your routes to lazy load modules, which means that Angular only loads modules as needed, rather than loading all modules when the app launches. Additionally, you can preload parts of your app in the background to improve the user experience.

關於延遲載入和預載入的詳情,請參閱專門的指南延遲載入 NgModule

For more information on lazy loading and preloading see the dedicated guide Lazy loading NgModules.

防止未經授權的訪問

Preventing unauthorized access

使用路由守衛來防止使用者未經授權就導航到應用的某些部分。Angular 中提供了以下路由守衛:

Use route guards to prevent users from navigating to parts of an app without authorization. The following route guards are available in Angular:

要想使用路由守衛,可以考慮使用無元件路由,因為這對於保護子路由很方便。

To use route guards, consider using component-less routes as this facilitates guarding child routes.

為你的守衛建立一項服務:

Create a service for your guard:

      
      ng generate guard your-guard
    

請在守衛類別裡實現你要用到的守衛。下面的例子使用 CanActivate 來保護該路由。

In your guard class, implement the guard you want to use. The following example uses CanActivate to guard the route.

Component (excerpt)
      
      export class YourGuard implements CanActivate {
  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): boolean {
      // your  logic goes here
  }
}
    

在路由模組中,在 routes 配置中使用相應的屬性。這裡的 canActivate 會告訴路由器它要協調到這個特定路由的導航。

In your routing module, use the appropriate property in your routes configuration. Here, canActivate tells the router to mediate navigation to this particular route.

Routing module (excerpt)
      
      {
  path: '/your-path',
  component: YourComponent,
  canActivate: [YourGuard],
}
    

關於此可工作範例的更多資訊,請參閱路由導航中關於路由守衛的部分

For more information with a working example, see the routing tutorial section on route guards.

連結引數陣列儲存路由導航時所需的成分:

A link parameters array holds the following ingredients for router navigation:

  • 指向目標元件的那個路由的路徑(path)

    The path of the route to the destination component.

  • 必備路由引數和可選路由引數,它們將進入該路由的 URL

    Required and optional route parameters that go into the route URL.

你可以把 RouterLink 指令繫結到一個數組,就像這樣:

You can bind the RouterLink directive to such an array like this:

src/app/app.component.ts (h-anchor)
      
      <a [routerLink]="['/heroes']">Heroes</a>
    

在指定路由引數時,使用如下的兩元素陣列:

The following is a two-element array when specifying a route parameter:

src/app/heroes/hero-list/hero-list.component.html (nav-to-detail)
      
      <a [routerLink]="['/hero', hero.id]">
  <span class="badge">{{ hero.id }}</span>{{ hero.name }}
</a>
    

你可以在物件中提供可選的路由引數,比如 { foo: 'foo' }

You can provide optional route parameters in an object, as in { foo: 'foo' }:

src/app/app.component.ts (cc-query-params)
      
      <a [routerLink]="['/crisis-center', { foo: 'foo' }]">Crisis Center</a>
    

這三個例子涵蓋了你在單級路由的應用中所需的一切。不過,在你新增一個像危機中心一樣的子路由時,你可以建立新連結陣列。

These three examples cover the needs of an app with one level of routing. However, with a child router, such as in the crisis center, you create new link array possibilities.

下面這個最小化 RouterLink 例子是基於危機中心指定的預設子路由建構的。

The following minimal RouterLink example builds upon a specified default child route for the crisis center.

src/app/app.component.ts (cc-anchor-w-default)
      
      <a [routerLink]="['/crisis-center']">Crisis Center</a>
    

請注意以下事項:

Note the following:

  • 陣列中的第一個條目標記出了父路由(/crisis-center)。

    The first item in the array identifies the parent route (/crisis-center).

  • 這個父路由沒有引數。

    There are no parameters for this parent route.

  • 沒有預設的子路由,因此你得選取一個。

    There is no default for the child route so you need to pick one.

  • 你決定跳轉到 CrisisListComponent,它的路由路徑是'/',但你不用顯式的新增它。

    You're navigating to the CrisisListComponent, whose route path is /, but you don't need to explicitly add the slash.

考慮以下路由器連結,它將從應用的根目錄導航到巨龍危機(Dragon Crisis):

Consider the following router link that navigates from the root of the application down to the Dragon Crisis:

src/app/app.component.ts (Dragon-anchor)
      
      <a [routerLink]="['/crisis-center', 1]">Dragon Crisis</a>
    
  • 陣列中的第一個條目標記出了父路由(/crisis-center)。

    The first item in the array identifies the parent route (/crisis-center).

  • 這個父路由沒有引數。

    There are no parameters for this parent route.

  • 陣列中的第二個條目('/:id')用來標記出到指定危機的詳情頁的子路由。

    The second item identifies the child route details about a particular crisis (/:id).

  • 詳細的子路由需要一個 id 路由引數。

    The details child route requires an id route parameter.

  • 你把巨龍危機id 新增為該陣列中的第二個條目(1)。

    You added the id of the Dragon Crisis as the second item in the array (1).

  • 最終產生的路徑是 /crisis-center/1

    The resulting path is /crisis-center/1.

你也可以把危機中心的路由單獨重新定義為 AppComponent 的範本:

You could also redefine the AppComponent template with Crisis Center routes exclusively:

src/app/app.component.ts (template)
      
      template: `
  <h1 class="title">Angular Router</h1>
  <nav>
    <a [routerLink]="['/crisis-center']">Crisis Center</a>
    <a [routerLink]="['/crisis-center/1', { foo: 'foo' }]">Dragon Crisis</a>
    <a [routerLink]="['/crisis-center/2']">Shark Crisis</a>
  </nav>
  <router-outlet></router-outlet>
`
    

總之,你可以用一級、兩級或多級路由來寫應用程式。 連結引數陣列提供了用來表示任意深度路由的連結引數陣列以及任意合法的路由引數序列、必須的路由器引數以及可選的路由引數物件。

In summary, you can write applications with one, two or more levels of routing. The link parameters array affords the flexibility to represent any routing depth and any legal sequence of route paths, (required) router parameters, and (optional) route parameter objects.

LocationStrategy 和瀏覽器的網址樣式

LocationStrategy and browser URL styles

當路由器導航到一個新的元件檢視時,它會用該檢視的 URL 來更新瀏覽器的當前地址以及歷史。 嚴格來說,這個 URL 其實是本地的,瀏覽器不會把該 URL 發給伺服器,並且不會重新載入此頁面。

When the router navigates to a new component view, it updates the browser's location and history with a URL for that view. As this is a strictly local URL the browser won't send this URL to the server and will not reload the page.

現代 HTML 5 瀏覽器支援history.pushState API, 這是一項可以改變瀏覽器的當前地址和歷史,卻又不會觸發伺服器端頁面請求的技術。 路由器可以合成出一個“自然的”URL,它看起來和那些需要進行頁面載入的 URL 沒什麼區別。

Modern HTML5 browsers support history.pushState, a technique that changes a browser's location and history without triggering a server page request. The router can compose a "natural" URL that is indistinguishable from one that would otherwise require a page load.

下面是危機中心的 URL 在“HTML 5 pushState”風格下的樣子:

Here's the Crisis Center URL in this "HTML5 pushState" style:

      
      localhost:3002/crisis-center/
    

老舊的瀏覽器在當前地址的 URL 變化時總會往伺服器傳送頁面請求……唯一的例外規則是:當這些變化位於“#”(被稱為“hash”)後面時不會發送。透過把應用內的路由 URL 拼接在 # 之後,路由器可以獲得這條“例外規則”帶來的優點。下面是到危機中心路由的“hash URL”:

Older browsers send page requests to the server when the location URL changes unless the change occurs after a "#" (called the "hash"). Routers can take advantage of this exception by composing in-application route URLs with hashes. Here's a "hash URL" that routes to the Crisis Center.

      
      localhost:3002/src/#/crisis-center/
    

路由器透過兩種 LocationStrategy 提供者來支援所有這些風格:

The router supports both styles with two LocationStrategy providers:

  1. PathLocationStrategy - 預設的策略,支援“HTML 5 pushState”風格。

    PathLocationStrategy—the default "HTML5 pushState" style.

  2. HashLocationStrategy - 支援“hash URL”風格。

    HashLocationStrategy—the "hash URL" style.

RouterModule.forRoot() 函式把 LocationStrategy 設定成了 PathLocationStrategy,使其成為了預設策略。 你還可以在啟動過程中改寫(override)它,來切換到 HashLocationStrategy 風格。

The RouterModule.forRoot() function sets the LocationStrategy to the PathLocationStrategy, which makes it the default strategy. You also have the option of switching to the HashLocationStrategy with an override during the bootstrapping process.

關於提供程式和引導過程的更多資訊,請參閱依賴注入

For more information on providers and the bootstrap process, see Dependency Injection.

選擇路由策略

Choosing a routing strategy

你必須在開發專案的早期就選擇一種路由策略,因為一旦該應用進入了生產階段,你網站的訪問者就會使用並依賴應用的這些 URL 參考。

You must choose a routing strategy early in the development of you project because once the application is in production, visitors to your site use and depend on application URL references.

幾乎所有的 Angular 專案都會使用預設的 HTML 5 風格。它產生的 URL 更易於被使用者理解,它也為將來做伺服器端渲染預留了空間。

Almost all Angular projects should use the default HTML5 style. It produces URLs that are easier for users to understand and it preserves the option to do server-side rendering.

在伺服器端渲染指定的頁面,是一項可以在該應用首次載入時大幅提升響應速度的技術。那些原本需要十秒甚至更長時間載入的應用,可以預先在伺服器端渲染好,並在少於一秒的時間內完整渲染在使用者的裝置上。

Rendering critical pages on the server is a technique that can greatly improve perceived responsiveness when the app first loads. An app that would otherwise take ten or more seconds to start could be rendered on the server and delivered to the user's device in less than a second.

只有當應用的 URL 看起來像是標準的 Web URL,中間沒有 hash(#)時,這個選項才能生效。

This option is only available if application URLs look like normal web URLs without hashes (#) in the middle.

<base href>

路由器使用瀏覽器的 history.pushState API 進行導航。藉助 pushState 你自訂應用中的 URL 路徑 localhost:4200/crisis-center,應用內的 URL 和伺服器的 URL 沒有區別。

The router uses the browser's history.pushState for navigation. pushState allows you to customize in-app URL paths; for example, localhost:4200/crisis-center. The in-app URLs can be indistinguishable from server URLs.

現代的 HTML5 瀏覽器都支援 pushState,這也就是為什麼很多人把這種 URL 形式稱為 "HTML 5" 風格的 URL。

Modern HTML5 browsers were the first to support pushState which is why many people refer to these URLs as "HTML5 style" URLs.

路由器預設使用 HTML5 風格的導航。 在 LocationStrategy 與瀏覽器 URL 風格部分,你可以瞭解為何推薦使用 HTML5 風格的 URL,如何調整其行為,以及必要時如何切換到老式的 hash(#)風格。

HTML5 style navigation is the router default. In the LocationStrategy and browser URL styles section, learn why HTML5 style is preferable, how to adjust its behavior, and how to switch to the older hash (#) style, if necessary.

你必須在應用的 index.html新增一個 <base href> 元素才能讓 pushState 路由正常工作。 瀏覽器要用 <base href> 的值為參考 CSS、指令碼和圖片檔案時使用的相對 URL 新增字首。

You must add a <base href> element to the app's index.html for pushState routing to work. The browser uses the <base href> value to prefix relative URLs when referencing CSS files, scripts, and images.

請把 <base> 元素新增在 <head> 標籤的緊後面。如果應用的根目錄是 app 目錄,那麼就可以像這個應用程式一樣,設定 index.html中的 href 值。程式碼如下。

Add the <base> element just after the <head> tag. If the app folder is the application root, as it is for this application, set the href value in index.html as shown here.

src/index.html (base-href)
      
      <base href="/">
    

HTML5 網址和 <base href>

HTML5 URLs and the <base href>

後面的指南中會參考 URL 的不同部分。下圖是這些部分所指內容的梗概:

The guidelines that follow will refer to different parts of a URL. This diagram outlines what those parts refer to:

      
      foo://example.com:8042/over/there?name=ferret#nose
\_/   \______________/\_________/ \_________/ \__/
 |           |            |            |        |
scheme    authority      path        query   fragment
    

由於路由器預設使用 “HTML 5 pushState” 風格,所以你必須用一個 <base href> 來配置該策略(Strategy)。

While the router uses the HTML5 pushState style by default, you must configure that strategy with a <base href>.

配置該策略的首選方式是往 index.html<head> 中新增一個<base href> element標籤。

The preferred way to configure the strategy is to add a <base href> element tag in the <head> of the index.html.

src/index.html (base-href)
      
      <base href="/">
    

如果沒有該標記,瀏覽器就可能無法在“深度連結”進入應用時載入資源(圖片,CSS,指令碼)。

Without that tag, the browser may not be able to load resources (images, CSS, scripts) when "deep linking" into the app.

有些開發人員可能無法新增 <base> 元素,這可能是因為它們沒有訪問 <head>index.html 的許可權。

Some developers may not be able to add the <base> element, perhaps because they don't have access to <head> or the index.html.

它們仍然可以使用 HTML 5 格式的 URL,但要採取如下步驟進行補救:

Those developers may still use HTML5 URLs by taking the following two steps:

  1. 用適當的[APP_BASE_HREF][]值提供(provide)路由器。

    Provide the router with an appropriate APP_BASE_HREF value.

  2. 對所有 Web 資源(CSS、圖片、指令碼和範本 HTML 檔案)使用根 URL(高優先度 URL)。

    Use root URLs (URLs with an authority) for all web resources: CSS, images, scripts, and template HTML files.

  • <base href>path 應該用 "/" 結尾,瀏覽器會忽略 path 中最右邊的 "/" 後面的字元。

    The <base href> path should end with a "/", as browsers ignore characters in the path that follow the right-most "/".

  • 如果 <base href> 包含 query 部分,則只有頁內連結的 path 部分為空並且沒有 query 時,才會使用這裡的 query。 這意味著 <base href> 中的 query 部分只有在使用 HashLocationStrategy 策略時才有用。

    If the <base href> includes a query part, the query is only used if the path of a link in the page is empty and has no query. This means that a query in the <base href> is only included when using HashLocationStrategy.

  • 如果頁內連結是根 URL(高優先度 URL),則 <base href> 不會使用。在這種方式下,APP_BASE_HREF 的優先度將會導致所有由 Angular 建立的連結忽略 <base href>

    If a link in the page is a root URL (has an authority), the <base href> is not used. In this way, an APP_BASE_HREF with an authority will cause all links created by Angular to ignore the <base href> value.

  • <base href> 中的片段(#後面的部分)永遠不會被使用。

    A fragment in the <base href> is never persisted.

對所有 Web 資源使用絕對地址:CSS、圖片、指令碼、範本 HTML。

For more complete information on how <base href> is used to construct target URIs, see the RFC section on transforming references.

HashLocationStrategy

你可以在根模組的 RouterModule.forRoot() 的第二個引數中傳入一個帶有 useHash: true 的物件,以回到基於 HashLocationStrategy 的傳統方式。

You can use HashLocationStrategy by providing the useHash: true in an object as the second argument of the RouterModule.forRoot() in the AppModule.

src/app/app.module.ts (hash URL strategy)
      
      import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { Routes, RouterModule } from '@angular/router';

import { AppComponent } from './app.component';
import { PageNotFoundComponent } from './page-not-found/page-not-found.component';

const routes: Routes = [

];

@NgModule({
  imports: [
    BrowserModule,
    FormsModule,
    RouterModule.forRoot(routes, { useHash: true })  // .../#/crisis-center/
  ],
  declarations: [
    AppComponent,
    PageNotFoundComponent
  ],
  providers: [

  ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }