根据Angular公式文档,理解Angular第3部分.
首先
我已经在Angular理解②中按照Angular官方文档的指导学习了路由设置的方法。接下来,我将继续按照官方文档的指导加深理解。
此外,由于本文正在进行本地环境的实施,因此使用了部分Angular CLI命令。有关本地环境的建立,请参考Angular官方教程中的本地环境设置部分。
Angular 教程
本文将根据数据管理的需要,采用修改和添加样本代码的方式进行进展。本文将执行以下操作。
-
- カートに入れた商品リストを管理するカートサービスを追加
-
- 商品の詳細ビューに Buy ボタンを追加
-
- カート内の商品を表示するカートコンポーネントを追加
- HttpClient を使用して .json ファイルから配送料金を取得する shipping コンポーネントを追加
创建购物车服务
通过使用 Angular 的依赖注入(DI,Dependency Injection),我们指的是在应用程序的任意部分可以使用的类的实例。在本教程中,我们将创建一个购物车服务,让用户可以将商品添加到购物车中并保存购物车内商品的信息。
1. 服务的产生
首先,使用Angular CLI命令创建一个新的服务。将服务命名为cart。
$ ng g s cart # ng generate service cart でも可
执行后,将创建 src/app/cart.service.ts 和 src/app/cart.service.spec.ts 文件。(本次不使用 src/app/cart.service.spec.ts 文件。)
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class CartService {
constructor() { }
}
因为对默认的@Injectable({providedIn: ‘root’})的意义不明,因此进行了调查。据说在@Injectable选项中的providedIn可以指定服务提供的范围,以提供依赖对象给模块。由于我不太能理解并且无法完全理解其含义,所以暂时将其放在这里。
2. 属性的定义
导入Product接口,并定义一个items属性,用于将商品数组存储到购物车中。
import { Injectable } from '@angular/core';
import { Product } from './products';
@Injectable({
providedIn: 'root'
})
export class CartService {
items: Product[] = [];
constructor() { }
}
3. 方法的定义
定义一个 addToCart 方法来将商品添加到购物车,定义一个 getItems 方法来获取商品列表,定义一个 clearCart 方法来清空商品列表。
import { Injectable } from '@angular/core';
import { Product } from './products';
@Injectable({
providedIn: 'root'
})
export class CartService {
items: Product[] = [];
constructor() { }
addToCart(product: Product) {
this.items.push(product);
}
getItems() {
return this.items;
}
clearCart() {
this.items = [];
return this.items;
}
}
使用购物车服务。
使用上述创建的购物车服务,将商品添加到购物车中。
1. 引入购物车服务
在”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';
...
购物车服务的提供
在product-details.component.ts中,添加并注入购物车服务到构造函数中,并定义使用注入的服务的addToCart方法。
...
export class ProductDetailsComponent implements OnInit {
product: Product | undefined;
constructor(
private route: ActivatedRoute,
private cartService: CartService
) {}
ngOnInit() {
// First get the product id from the current route.
const routeParams = this.route.snapshot.paramMap;
const productIdFromRoute = Number(routeParams.get('productId'));
// Find the product that correspond with the id provided in route.
this.product = products.find(product => product.id === productIdFromRoute);
}
addToCart(product: Product) {
this.cartService.addToCart(product);
window.alert('Your product has been added to the cart!');
}
}
3. 事件绑定
将点击(click)事件绑定到上述定义的方法中的“购买”按钮。
<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. 组件的创建
首先,使用 Angular CLI 命令创建一个新的组件。将服务命名为 cart.
$ ng g c cart # ng generate component cart でも可
执行后,将创建src/app/cart目录。
2. 添加路由
为了处理创建的购物车组件,需要在app.module.ts中添加路径。(我认为还需要在declarations中添加,但是系统已经自动添加了。)
...
@NgModule({
imports: [
BrowserModule,
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 {}
3. 添加 routerLink
请添加 routerLink 指令,将点击“Checkout”按钮后导航至上述添加到 /cart 的 URL。
<a [routerLink]="['/']">
<h1>My Store</h1>
</a>
<a routerLink="/cart" class="button fancy-button">
<i class="material-icons">shopping_cart</i>
Checkout
</a>
当按下Checkout按钮时可以确认页面会发生转换。
在这里,使用My Store按钮的routerLink指令的写法([routerLink]=”[‘/’]”)似乎对包含变量(动态变化)的URL很有帮助,但在当前情况下只是看起来很冗长。我们可以将其简化为与Checkout按钮相同的routerLink=”/”。
4. 使用服务
刚才我在product-details.component.ts中使用购物车服务将商品添加到购物车中。现在我想在新创建的购物车组件中显示已添加到购物车的商品列表。因此,在cart.component.ts中我使用购物车服务来获取商品列表。
export class CartComponent {
items = this.cartService.getItems();
constructor(
private cartService: CartService
) { }
}
根据以上规定,购物车中的商品列表将被存储在items属性中。最后,在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>
可以看到各种不同的实施方式。
最后
在数据管理方面,虽然还有使用 HttpClient 等的方法,但我决定现在先暂时停止。因为我已经理解了 Angular 的基本组件、模板、服务和依赖注入,所以在之后实际开发应用程序时,如果遇到不明白的部分,我会逐步调查并继续进行下去。