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

管理資料

Managing data

本章基於以一個基本 Anguluar 應用快速上手的第二步 —— 新增導航。 在此開發階段,本商店應用具有一個包含兩個檢視的商品名錄:商品列表和商品詳情。使用者點選清單中的某個商品名稱,就會在新檢視中看到具有專門的 URL 或路由的詳情頁。

This guide builds on the second step of the Getting started with a basic Angular application tutorial, Adding navigation. At this stage of development, the store application has a product catalog with two views: a product list and product details. Users can click on a product name from the list to see details in a new view, with a distinct URL, or route.

本頁將指導你分三個步驟建立購物車:

This step of the tutorial guides you through creating a shopping cart in the following phases:

  • 修改商品詳情檢視,讓它包含一個 “Buy” 按鈕,它會把當前商品新增到由 "購物車服務" 管理的商品列表中。

    Update the product details view to include a Buy button, which adds the current product to a list of products that a cart service manages.

  • 新增一個購物車元件,它會顯示購物車中的商品。

    Add a cart component, which displays the items in the cart.

  • 新增一個配送元件,它會使用 Angular 的 HttpClient.json 檔案中檢索配送資料來取得購物車中這些商品的運費。

    Add a shipping component, which retrieves shipping prices for the items in the cart by using Angular's HttpClient to retrieve shipping data from a .json file.

建立購物車服務

Create the shopping cart service

在 Angular 中, 服務是類別的一個實例, 藉助 Angular 的依賴注入體系,你可以在應用中的任意部分使用它。

In Angular, a service is an instance of a class that you can make available to any part of your application using Angular's dependency injection system.

現在, 使用者可以瀏覽產品資訊,而應用可以模擬分享產品,以及發出產品變更通知。

Currently, users can view product information, and the application can simulate sharing and notifications about product changes.

下一步是為使用者提供一種把產品新增到購物車中的方法。 本章節將帶領你新增一個 Buy 按鈕並且建立一個購物車服務以儲存購物車中的產品資訊。

The next step is to build a way for users to add products to a cart. This section walks you through adding a Buy button and setting up a cart service to store information about products in the cart.

定義購物車服務

Define a cart service

  1. 要想產生購物車服務,請右鍵單擊 app 資料夾,選擇 Angular Generator,並選擇 Service。把這個新服務命名為 cart

    To generate a cart service, right click on the app folder, choose Angular Generator, and choose Service. Name the new service cart.

    src/app/cart.service.ts
          
          import { Injectable } from '@angular/core';
    
    @Injectable({
      providedIn: 'root'
    })
    export class CartService {
    
      constructor() {}
    
    }
        
  2. CartService 類別中,定義一個 items 屬性來把當前商品的陣列儲存在購物車中。

    In the CartService class, define an items property to store the array of the current products in the cart.

    src/app/cart.service.ts
          
          export class CartService {
      items: Product[] = [];
    }
        
  3. 定義把商品新增到購物車、返回購物車商品以及清除購物車商品的方法:

    Define methods to add items to the cart, return cart items, and clear the cart items.

    src/app/cart.service.ts
          
          export class CartService {
      items: Product[] = [];
    
      addToCart(product: Product) {
        this.items.push(product);
      }
    
      getItems() {
        return this.items;
      }
    
      clearCart() {
        this.items = [];
        return this.items;
      }
    }
        
  • addToCart() 方法會將產品附加到 items 陣列中。

    The addToCart() method appends a product to an array of items.

    • getItems() 方法會收集使用者加到購物車中的商品,並返回每個商品及其數量。

      The getItems() method collects the items users add to the cart and returns each item with its associated quantity.

    • clearCart() 方法返回一個空陣列。

      The clearCart() method returns an empty array of items, which empties the cart.

使用購物車服務

Use the cart service

本節會教你使用 CartService 來把一個商品新增到購物車中。

This section walks you through using the CartService to add a product to the cart.

  1. product-details.component.ts 中匯入購物車服務。

    In product-details.component.ts, import the cart service.

    src/app/product-details/product-details.component.ts
          
          import { Component, OnInit } from '@angular/core';
    import { ActivatedRoute } from '@angular/router';
    
    import { Product, products } from '../products';
    import { CartService } from '../cart.service';
        
    1. 透過把購物車服務注入到這裡的 constructor() 中來注入它。

      Inject the cart service by adding it to the constructor().

      src/app/product-details/product-details.component.ts
            
            export class ProductDetailsComponent implements OnInit {
        constructor(
          private route: ActivatedRoute,
          private cartService: CartService
        ) { }
      }
          
  2. 定義 addToCart() 方法,該方法會當前商品新增到購物車中。

    Define the addToCart() method, which adds the current product to the cart.

    src/app/product-details/product-details.component.ts
          
          export class ProductDetailsComponent implements OnInit {
      addToCart(product: Product) {
        this.cartService.addToCart(product);
        window.alert('Your product has been added to the cart!');
      }
    }
        

    addToCart() 方法做了如下事情:

    The addToCart() method does the following:

    • 以當前'product'作為引數。

      Takes the current product as an argument.

    • 使用 CartService addToCart() 方法去新增產品到購物車中。

      Uses the CartService addToCart() method to add the product to the cart.

    • 顯示一條你已經添加了一個產品到購物車到訊息。

      Displays a message that you've added a product to the cart.

  3. product-details.component.html 中,新增一個帶有 Buy 標籤的按鈕,並且把其 click() 事件繫結到 addToCart() 方法上。 這段程式碼會為產品詳情範本新增一個 Buy 按鈕,並把當前產品新增到購物車中。

    In product-details.component.html, add a button with the label Buy, and bind the click() event to the addToCart() method. This code updates the product details template with a Buy button that adds the current product to the cart.

    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>
    
      <button (click)="addToCart(product)">Buy</button>
    </div>
        
  1. 重新整理應用,以驗證新的 Buy 按鈕如預期般出現了,並且單擊某個產品的名稱,以展示其詳情。

    Verify that the new Buy button appears as expected by refreshing the application and clicking on a product's name to display its details.

  2. 點選“Buy”按鈕來把該商品新增到購物車中儲存的商品列表中,並顯示一條確認訊息。

    Click the Buy button to add the product to the stored list of items in the cart and display a confirmation message.

建立購物車檢視

Create the cart view

為了讓顧客看到他們的購物車,你可以用兩步建立購物車檢視:

For customers to see their cart, you can create the cart view in two steps:

  1. 建立一個購物車元件並配置指向這個新元件的路由。

    Create a cart component and configure routing to the new component.

  2. 顯示購物車商品

    Display the cart items.

設定該元件

Set up the cart component

要建立購物車檢視,可遵循與建立 ProductDetailsComponent 相同的步驟,並且為這個新元件配置路由。

To create the cart view, follow the same steps you did to create the ProductDetailsComponent and configure routing for the new component.

  1. 右鍵單擊 app 資料夾,選擇 Angular GeneratorComponent 以產生一個名為 cart 的購物車元件。

    Generate a cart component named cart by right-clicking the app folder, choosing Angular Generator, and Component.

    src/app/cart/cart.component.ts
          
          import { Component } from '@angular/core';
    
    @Component({
      selector: 'app-cart',
      templateUrl: './cart.component.html',
      styleUrls: ['./cart.component.css']
    })
    export class CartComponent {
    
      constructor() { }
    
    }
        

    StackBlitz 預設還會在元件中產生一個 ngOnInit()。不過在本課程中,你可以忽略 CartComponentngOnInit()

    StackBlitz also generates an ngOnInit() by default in components. You can ignore the CartComponent ngOnInit() for this tutorial.

  2. 開啟 app.module.ts,為元件 CartComponent 新增一個路由,其路由為 cart

    Open app.module.ts and add a route for the component CartComponent, with a path of cart.

    src/app/app.module.ts
          
          @NgModule({
      imports: [
        BrowserModule,
        ReactiveFormsModule,
        RouterModule.forRoot([
          { path: '', component: ProductListComponent },
          { path: 'products/:productId', component: ProductDetailsComponent },
          { path: 'cart', component: CartComponent },
        ])
      ],
        
  3. 修改 "Checkout" 按鈕,以便讓它路由到 /cart。 在 top-bar.component.html 中新增一個指向 /cartrouterLink 指令。

    Update the Checkout button so that it routes to the /cart URL. In top-bar.component.html, add a routerLink directive pointing to /cart.

    src/app/top-bar/top-bar.component.html
          
          <a routerLink="/cart" class="button fancy-button">
      <i class="material-icons">shopping_cart</i>Checkout
    </a>
        
  4. 要檢視新的購物車元件,請點選“Checkout”按鈕。你會看到預設文字“cart works!”,該 URL 的格式為 https://getting-started.stackblitz.io/cart,其中的 getting-started.stackblitz.io 部分可能與你的 StackBlitz 專案不同。

    Verify the new CartComponent works as expected by clicking the Checkout button. You can see the "cart works!" default text, and the URL has the pattern https://getting-started.stackblitz.io/cart, where getting-started.stackblitz.io may be different for your StackBlitz project.

顯示購物車商品

Display the cart items

本節將告訴你如何修改購物車元件以使用購物車服務來顯示購物車中的商品。

This section shows you how to use the cart service to display the products in the cart.

  1. cart.component.ts 中,從 cart.service.ts 檔案中匯入 CartService

    In cart.component.ts, import the CartService from the cart.service.ts file.

    src/app/cart/cart.component.ts
          
          import { Component } from '@angular/core';
    import { CartService } from '../cart.service';
        
    1. 注入 CartService,以便購物車元件可以使用它。

      Inject the CartService so that the CartComponent can use it by adding it to the constructor().

      src/app/cart/cart.component.ts
            
            export class CartComponent {
      
        constructor(
          private cartService: CartService
        ) { }
      }
          
  2. 定義 items 屬性,以便把商品存放在購物車中。

    Define the items property to store the products in the cart.

    src/app/cart/cart.component.ts
          
          export class CartComponent {
      items = this.cartService.getItems();
    
      constructor(
        private cartService: CartService
      ) { }
    }
        

    這段程式碼使用 CartServicegetItems() 方法來設定條目。你以前在建立 cart.service.ts時定義過此方法。

    This code sets the items using the CartService getItems() method. You defined this method when you created cart.service.ts.

  3. 修改範本,加上標題,用帶有 *ngFor<div> 來顯示每個購物車商品的名字和價格。

    Update the cart template with a header, and use a <div> with an *ngFor to display each of the cart items with its name and price.

    產生的 CartComponent 範本如下:

    The resulting CartComponent template is as follows.

    src/app/cart/cart.component.html
          
          <h3>Cart</h3>
    
    <div class="cart-item" *ngFor="let item of items">
      <span>{{ item.name }}</span>
      <span>{{ item.price | currency }}</span>
    </div>
        
  4. 驗證你的購物車如預期般工作:

    Verify that your cart works as expected:

    • 點選 My Store

      Click My Store

    • 單擊商品名稱以顯示其詳細資訊。

      Click on a product name to display its details.

    • 點選Buy 將商品新增到購物車。

      Click Buy to add the product to the cart.

    • 點選Checkout檢視購物車。

      Click Checkout to see the cart.

要了解關於服務的更多資訊,請參閱“服務和依賴注入簡介”

For more information about services, see Introduction to Services and Dependency Injection.

檢索運費價格

Retrieve shipping prices

伺服器通常採用流的形式返回資料。 流是很有用的,因為它們可以很容易地轉換返回的資料,也可以修改你請求資料的方式。 Angular 的 HTTP 客戶端( HttpClient )是一種內建的方式,可以從外部 API 中獲取資料,並以流的形式提供給你的應用。

Servers often return data in the form of a stream. Streams are useful because they make it easy to transform the returned data and make modifications to the way you request that data. Angular HttpClient is a built-in way to fetch data from external APIs and provide them to your application as a stream.

本節會為你展示如何使用 HttpClient 從外部檔案中檢索運費。

This section shows you how to use HttpClient to retrieve shipping prices from an external file.

在本指南的 StackBlitz 應用中,透過 assets/shipping.json 檔案提供了一些預定義的配送資料。你可以利用這些資料為購物車中的商品新增運費。

The application that StackBlitz generates for this guide comes with predefined shipping data in assets/shipping.json. Use this data to add shipping prices for items in the cart.

src/assets/shipping.json
      
      [
  {
    "type": "Overnight",
    "price": 25.99
  },
  {
    "type": "2-Day",
    "price": 9.99
  },
  {
    "type": "Postal",
    "price": 2.99
  }
]
    

配置 AppModule 以使用 HttpClient

Configure AppModule to use HttpClient

要使用 Angular 的 HTTP 客戶端之前,你必須先配置你的應用來使用 HttpClientModule

To use Angular's HttpClient, you must configure your application to use HttpClientModule.

Angular 的 HttpClientModule 中註冊了在整個應用中使用 HttpClient 服務的單個實例所需的服務提供者。

Angular's HttpClientModule registers the providers your application needs to use the HttpClient service throughout your application.

  1. app.module.ts 的頂部從 @angular/common/http 套件中匯入 HttpClientModule 以及其它匯入項。 由於有很多其它匯入項,因此這裡的程式碼片段省略它們,以保持簡潔。請確保現有的匯入都還在原地。

    In app.module.ts, import HttpClientModule from the @angular/common/http package at the top of the file with the other imports. As there are a number of other imports, this code snippet omits them for brevity. Be sure to leave the existing imports in place.

    src/app/app.module.ts
          
          import { HttpClientModule } from '@angular/common/http';
        
  2. HttpClientModule 新增到 AppModule @NgModule()imports 陣列中,以便全域性註冊 Angular 的 HttpClient

    To register Angular's HttpClient providers globally, add HttpClientModule to the AppModule @NgModule() imports array.

    src/app/app.module.ts
          
          @NgModule({
      imports: [
        BrowserModule,
        HttpClientModule,
        ReactiveFormsModule,
        RouterModule.forRoot([
          { path: '', component: ProductListComponent },
          { path: 'products/:productId', component: ProductDetailsComponent },
          { path: 'cart', component: CartComponent },
        ])
      ],
      declarations: [
        AppComponent,
        TopBarComponent,
        ProductListComponent,
        ProductAlertsComponent,
        ProductDetailsComponent,
        CartComponent,
      ],
      bootstrap: [
        AppComponent
      ]
    })
    export class AppModule { }
        

配置 CartService 以使用 HttpClient

Configure CartService to use HttpClient

下一步是注入 HttpClient 服務到你的服務中, 這樣你的應用可以獲取資料並且與外部API和資源互動。

The next step is to inject the HttpClient service into your service so your application can fetch data and interact with external APIs and resources.

  1. @angular/common/http 套件中匯入 HttpClient

    In cart.service.ts, import HttpClient from the @angular/common/http package.

    src/app/cart.service.ts
          
          import { Injectable } from '@angular/core';
    import { HttpClient } from '@angular/common/http';
    import { Product } from './products';
        
  2. HttpClient 注入到 CartService 的建構函式中:

    Inject HttpClient into the CartService constructor().

    src/app/cart.service.ts
          
          export class CartService {
      items: Product[] = [];
    
      constructor(
        private http: HttpClient
      ) {}
    }
        

配置 CartService 以得到商品價格

Configure CartService to get shipping prices

要從 shapping.json 中得到商品資料, 你可以使用 HttpClient get() 方法。

To get shipping data, from shipping.json, You can use the HttpClient get() method.

  1. cart.service.tsclearCart() 方法下面,定義一個新的 getShippingPrices() 方法,該方法會呼叫 HttpClient#get() 方法。

    In cart.service.ts, below the clearCart() method, define a new getShippingPrices() method that uses the HttpClient get() method.

    src/app/cart.service.ts
          
          export class CartService {
      getShippingPrices() {
        return this.http.get<{type: string, price: number}[]>('/assets/shipping.json');
      }
    }
        

要了解關於 Angular HttpClient 的更多資訊,請參閱客戶端-伺服器整合指南。

For more information about Angular's HttpClient, see the Client-Server Interaction guide.

建立配送元件

Create a shipping component

現在你的應用已經可以檢索配送資料了,你還要建立一個配送元件和相關的範本。

Now that you've configured your application to retrieve shipping data, you can create a place to render that data.

  1. 右鍵單擊 app 資料夾,選擇 Angular GeneratorComponent 來產生一個名為 shipping 的新元件。

    Generate a new component named shipping by right-clicking the app folder, choosing Angular Generator, and selecting Component.

    src/app/shipping/shipping.component.ts
          
          import { Component } from '@angular/core';
    
    @Component({
      selector: 'app-shipping',
      templateUrl: './shipping.component.html',
      styleUrls: ['./shipping.component.css']
    })
    export class ShippingComponent {
    
      constructor() { }
    
    }
        
  2. app.module.ts 中,新增一個配送路由。其 pathshipping,其 component 為 ShippingComponent

    In app.module.ts, add a route for shipping. Specify a path of shipping and a component of ShippingComponent.

    src/app/app.module.ts
          
          @NgModule({
      imports: [
        BrowserModule,
        HttpClientModule,
        ReactiveFormsModule,
        RouterModule.forRoot([
          { path: '', component: ProductListComponent },
          { path: 'products/:productId', component: ProductDetailsComponent },
          { path: 'cart', component: CartComponent },
          { path: 'shipping', component: ShippingComponent },
        ])
      ],
      declarations: [
        AppComponent,
        TopBarComponent,
        ProductListComponent,
        ProductAlertsComponent,
        ProductDetailsComponent,
        CartComponent,
        ShippingComponent
      ],
      bootstrap: [
        AppComponent
      ]
    })
    export class AppModule { }
        

    新的配送元件尚未連結到任何其它元件,但你可以透過輸入其路由指定的 URL 在預覽窗格中看到它的範本。該 URL 具有以下模式:https://getting-started.stackblitz.io/shipping,其中的 gets-started.stackblitz.io 部分可能與你的 StackBlitz 專案不同。

    There's no link to the new shipping component yet, but you can see its template in the preview pane by entering the URL its route specifies. The URL has the pattern: https://getting-started.stackblitz.io/shipping where the getting-started.stackblitz.io part may be different for your StackBlitz project.

配置 ShippingComponent 以使用 CartService

Configuring the ShippingComponent to use CartService

這個章節將指導你修改 ShappingComponent 以透過HTTP從 shipping.json 檔案中提取商品資料。

This section guides you through modifying the ShippingComponent to retrieve shipping data via HTTP from the shipping.json file.

  1. shipping.component.ts 中匯入 CartService

    In shipping.component.ts, import CartService.

    src/app/shipping/shipping.component.ts
          
          import { Component } from '@angular/core';
    
    import { CartService } from '../cart.service';
        

  2. 把購物車服務注入到 ShippingComponentconstructor() 建構函式中:

    Inject the cart service in the ShippingComponent constructor().

    src/app/shipping/shipping.component.ts
          
          constructor(private cartService: CartService) {
    }
        

    1. 定義一個 shippingCosts 屬性,並從 CartService 中利用購物車服務的 getShippingPrices() 方法設定它。

      Define a shippingCosts property that sets the shippingCosts property using the getShippingPrices() method from the CartService.

      src/app/shipping/shipping.component.ts
            
            export class ShippingComponent {
        shippingCosts = this.cartService.getShippingPrices();
      }
          
  3. 利用 async 管道修改配送元件的範本,以顯示配送型別和價格:

    Update the ShippingComponent template to display the shipping types and prices using the async pipe.

    src/app/shipping/shipping.component.html
          
          <h3>Shipping Prices</h3>
    
    <div class="shipping-item" *ngFor="let shipping of shippingCosts | async">
      <span>{{ shipping.type }}</span>
      <span>{{ shipping.price | currency }}</span>
    </div>
        

    async 管道從資料流中返回最新值,並在所屬元件的生命期內持續返回。當 Angular 銷燬該元件時,async 管道會自動停止。關於 async 管道的詳細資訊,請參閱 AsyncPipe API 文件

    The async pipe returns the latest value from a stream of data and continues to do so for the life of a given component. When Angular destroys that component, the async pipe automatically stops. For detailed information about the async pipe , see the AsyncPipe API documentation.

  4. 在購物車檢視中新增一個到配送檢視的連結:

    Add a link from the CartComponent view to the ShippingComponent view.

    src/app/cart/cart.component.html
          
          <h3>Cart</h3>
    
    <p>
      <a routerLink="/shipping">Shipping Prices</a>
    </p>
    
    <div class="cart-item" *ngFor="let item of items">
      <span>{{ item.name }}</span>
      <span>{{ item.price | currency }}</span>
    </div>
        
  5. 點選 Checkout 按鈕,檢視更新後的購物車。注意,修改本應用會導致預覽窗格重新整理,這會清空購物車。

    Click the Checkout button to see the updated cart. Remember that changing the application causes the preview to refresh, which empties the cart.

    點選此連結可以導航到運費頁。

    Click on the link to navigate to the shipping prices.

下一步

What's next

現在你有了一個帶有商品名錄和購物車的商店應用了,而且你還可以查詢運費。

You now have a store application with a product catalog, a shopping cart, and you can look up shipping prices.

要繼續探索 Angular,你可以:

To continue exploring Angular:

  • 繼續閱讀表單與使用者輸入部分,新增購物車檢視和結賬檢視,以完成本應用。

    Continue to Forms for User Input to finish the application by adding the shopping cart view and a checkout form.

  • 跳到部署部分來轉為本地開發,或者把你的應用部署到 Firebase 或你自己的伺服器上。

    Skip ahead to Deployment to move to local development, or deploy your application to Firebase or your own server.