填写这份《一分钟调查》,帮我们(开发组)做得更好!去填写Home

路由

Routing

你的第一个应用结束时,这个在线商店应用会有一个基本的商品名录。该应用还没有任何可变的状态或导航。它只有一个 URL,该 URL 总是会显示“我的商店”页面,其中是商品列表及其描述。

At the end of Your First App, the online store application has a basic product catalog. The app doesn't have any variable states or navigation. There is one URL, and that URL always displays the "My Store" page with a list of products and their descriptions.

在本节中,你将扩展本应用以便在单独的页面中显示完整的商品详情,并让它使用自己的 URL。

In this section, you'll extend the app to display full product details in separate pages, with their own URLs.

为此,你要使用 Angular 的路由器。借助 Angular 路由器,你可以根据用户在应用中的位置向用户显示不同的组件和数据。当用户执行应用任务时,路由器可以从一个视图导航到另一个视图。

To do this, you'll use the Angular router. The Angular router enables you to show different components and data to the user based on where the user is in the application. The router enables navigation from one view to the next as users perform application tasks:

  • 在地址栏中输入一个 URL,浏览器就会导航到相应的页面。

    Enter a URL in the address bar, and the browser navigates to a corresponding page.

  • 点击页面上的链接,浏览器会导航到新页面。

    Click links on the page, and the browser navigates to a new page.

  • 点击浏览器的后退和前进按钮,浏览器会在你看过的页面历史中前后导航。

    Click the browser's back and forward buttons, and the browser navigates backward and forward through the history of pages you've seen.

注册路由

Registering a route

该应用已经设置为使用 Angular 路由器,并通过路由导航到之前修改过的商品列表组件。让我们来定义一个可以显示商品详情的路由。

The app is already set up to use the Angular router and to use routing to navigate to the product list component you modified earlier. Let's define a route to show individual product details.

  1. 为商品详情生成一个新组件。把组件命名为 product-details

    Generate a new component for product details. Give the component the name product-details.

    提示:在文件列表框中,右键单击 app 文件夹,选择 Angular GeneratorComponent

    Reminder: In the file list, right-click the app folder, choose Angular Generator and Component.

  2. app.module.ts 中,添加一个商品详情路由,该路由的 pathproducts/:productIdcomponentProductDetailsComponent

    In app.module.ts, add a route for product details, with a path of products/:productId and ProductDetailsComponent for the component.

    @NgModule({ imports: [ BrowserModule, ReactiveFormsModule, RouterModule.forRoot([ { path: '', component: ProductListComponent }, { path: 'products/:productId', component: ProductDetailsComponent }, ]) ],
    src/app/app.module.ts
          
          @NgModule({
      imports: [
        BrowserModule,
        ReactiveFormsModule,
        RouterModule.forRoot([
          { path: '', component: ProductListComponent },
          { path: 'products/:productId', component: ProductDetailsComponent },
        ])
      ],
        

    路由会将一个或多个 URL 路径与一个组件关联起来。

    A route associates one or more URL paths with a component.

  3. 使用 RouterLink 指令定义一个链接。routerLink 定义了如何在组件模板中声明式的导航到指定路由(或 URL)。

    Define a link using the RouterLink directive. The routerLink defines how the user navigates to the route (or URL) declaratively in the component template.

    我们希望用户点击商品名称来显示该商品的详情。

    We want the user to click a product name to display the details for that product.

    1. 打开 product-list.component.html

      Open product-list.component.html.

    2. 修改 *ngFor 指令,在遍历列表的过程中把 products 数组中的每个索引赋值给 productId 变量。

      Update the *ngFor directive to assign each index in the products array to the productId variable when iterating over the list.

    3. 修改商品名称的链接,使其包含 routerLink

      Modify the product name anchor to include a routerLink.

    <div *ngFor="let product of products; index as productId"> <h3> <a [title]="product.name + ' details'" [routerLink]="['/products', productId]"> {{ product.name }} </a> </h3> <!-- . . . --> </div>
    src/app/product-list/product-list.component.html
          
          <div *ngFor="let product of products; index as productId">
    
      <h3>
        <a [title]="product.name + ' details'" [routerLink]="['/products', productId]">
          {{ product.name }}
        </a>
      </h3>
    <!-- . . . -->
    </div>
        

    RouterLink 指令让路由器控制了一个链接元素。在这种情况下,路由(URL)包含一个固定的区段( /products ),但其最后一个区段是变量,要插入当前商品的 id 属性。例如,id 为 1 的商品的 URL 类似于 https://getting-started-myfork.stackblitz.io/products/1

    The RouterLink directive gives the router control over the anchor element. In this case, the route (URL) contains one fixed segment (/products) and the final segment is variable, inserting the id property of the current product. For example, the URL for a product with an id of 1 will be similar to https://getting-started-myfork.stackblitz.io/products/1.

  4. 通过单击商品名称来测试路由器。该应用会显示商品详情组件,该组件目前始终显示 “product-details works!” (我们将在下一节修复此问题。)

    Test the router by clicking a product name. The app displays the product details component, which currently always says "product-details works!" (We'll fix this in the next section.)

    注意,预览窗口中的 URL 会发生变化。其最后一段是 products/1

    Notice that the URL in the preview window changes. The final segment is products/1.

    Product details page with updated URL

使用路由信息

Using route information

商品详情组件负责处理每个商品的显示。Angular 的路由器会根据浏览器的 URL 和你定义的这些路由来决定如何显示组件。你可以通过 Angular 的路由器来组合使用 products 数据和路由信息,以显示每个商品的详情。

The product details component handles the display of each product. The Angular Router displays components based on the browser's URL and your defined routes. You'll use the Angular Router to combine the products data and route information to display the specific details for each product.

  1. 打开 product-details.component.ts 文件

    Open product-details.component.ts

  2. 改用外部文件中的商品数据。

    Arrange to use product data from an external file.

    1. @angular/router 包导入 ActivatedRoute,从 ../products 文件导入 products 数组。

      Import ActivatedRoute from the @angular/router package, and the products array from ../products.

      import { Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { products } from '../products';
      src/app/product-details/product-details.component.ts
            
            import { Component, OnInit } from '@angular/core';
      import { ActivatedRoute } from '@angular/router';
      
      import { products } from '../products';
          
    2. 定义 product 属性,并把 ActivatedRoute 注入到构造函数中。

      Define the product property and inject the ActivatedRoute into the constructor.

      export class ProductDetailsComponent implements OnInit { product; constructor( private route: ActivatedRoute, ) { } }
      src/app/product-details/product-details.component.ts
            
            export class ProductDetailsComponent implements OnInit {
        product;
      
        constructor(
          private route: ActivatedRoute,
        ) { }
      
      }
          

      ActivatedRoute 专门用于由 Angular 路由器加载的每个路由组件。它包含关于该路由,路由参数以及与该路由关联的其它数据的信息。

      The ActivatedRoute is specific to each routed component loaded by the Angular Router. It contains information about the route, its parameters, and additional data associated with the route.

  3. ngOnInit() 方法中,订阅(subscribe)路由参数并根据其 productId 获取商品信息。

    In the ngOnInit() method, subscribe to route params and fetch the product based on the productId.

    ngOnInit() { this.route.paramMap.subscribe(params => { this.product = products[+params.get('productId')]; }); }
          
          ngOnInit() {
      this.route.paramMap.subscribe(params => {
        this.product = products[+params.get('productId')];
      });
    }
        

    这个路由参数对应于路由中定义的路径变量。productId 是从与该路由匹配的 URL 中提供的。你可以通过 productId 来显示每个单独商品的详细信息。

    The route parameters correspond to the path variables defined in the route. The productId is provided from the URL that was matched to the route. You use the productId to display the details for each unique product.

  4. 修改模板,在 *ngIf 中显示商品详情。

    Update the template to display product details information inside an *ngIf.

    <h2>Product Details</h2> <div *ngIf="product"> <h3>{{ product.name }}</h3> <h4>{{ product.price | currency }}</h4> <p>{{ product.description }}</p> </div>
    src/app/product-details/product-details.component.html
          
          <h2>Product Details</h2>
    
    <div *ngIf="product">
      <h3>{{ product.name }}</h3>
      <h4>{{ product.price | currency }}</h4>
      <p>{{ product.description }}</p>
    
    </div>
        

现在,当用户点击商品列表中的某个名字时,路由器就会导航到商品的不同网址,用商品详情组件代替商品列表组件,并显示商品详情。

Now, when the user clicks on a name in the product list, the router navigates you to the distinct URL for the product, swaps out the product list component for the product details component, and displays the product details.

Product details page with updated URL and full details displayed

要了解关于 Angular 路由器的更多信息,请参阅路由和导航

Learn more: See Routing & Navigation for more information about the Angular router.

下一步

Next steps

恭喜!你已经把路由集成到你的在线商店了。

Congratulations! You have integrated routing into your online store.

  • 从商品列表页面链接到了单个商品

    Products are linked from the product list page to individual products

  • 用户可以点击列表中的某个商品名称来在新视图中查看其详细信息,并带有显著的 URL(路由)

    Users can click on a product name from the list to see details in a new view, with a distinct URL (route)

要继续探索 Angular,请选择以下选项之一:

To continue exploring Angular, choose either of the following options: