# Angular 入门

Angular 欢迎你!

本教程将通过构建一个电子商务网站,向你介绍 Angular 的基本知识。该网站具有商品名录、购物车和结账表单。

为了帮助你更好地起步,本教程提供了一个已完成的应用,你可以在 Stackblitz 上试验及互动,而不用建立本地开发环境。StackBlitz 是一个基于浏览器的开发环境,你可以在其中使用各种技术来创建、保存和共享项目。

# 前提条件

为了充分利用本教程,你应该已经对以下内容有基本的了解。

  • HTML

  • JavaScript

  • TypeScript

# 浏览范例应用

你可以用组件构建 Angular 应用。组件定义了 UI 中的职责范围,让你可以复用某些 UI 功能集。

一个组件由三部分组成:

部分 Component Part 详情 Details
组件类A component class 处理数据和功能。Handles data and functionality
HTML 模板An HTML template 决定 UI。Determines the UI
组件专属样式Component-specific styles 定义外观和感觉。Define the look and feel

本指南演示了如何使用下列组件构建应用。

组件 Components 详情 Details
<app-root> 第一个加载的组件,并且是其他组件的容器。The first component to load and the container for the other components
<app-top-bar> 商店名称和结帐按钮。The store name and checkout button
<app-product-list> 产品列表。The product list
<app-product-alerts> 包含应用中各种通知的组件。A component that contains the application's alerts

Online store with three components 有关组件的更多信息,请参见组件简介。

# 创建范例项目

要创建范例项目,请在 StackBlitz 中生成一个预置的范例项目在 StackBlitz 中生成一个预置的范例项目。要保存你的工作,请执行以下操作:

  • 登录到 StackBlitz。

  • 对你生成的项目进行分支。

  • 定时保存。

Fork the project 在 StackBlitz 中,右侧的预览窗格会显示范例应用的启动状态。此预览有两个区域:

  • 带有商店名称(My Store)和结账按钮的顶部栏

  • 产品列表(Products)及其标题

Starter online store application 左侧的项目区显示了构成本应用的源文件,包括基础结构和配置文件。

当你生成本教程随附的 StackBlitz 范例应用时,StackBlitz 会为你创建启动程序文件和模拟数据。本教程中用到的文件位于 src文件夹中。

有关如何使用 StackBlitz 的更多信息,请参见 StackBlitz 的文档

# 创建产品列表

在本节中,你将修改应用以显示产品列表。你会用到来自 products.ts文件的预定义产品数据,和一些来自 product-list.component.ts文件的方法。本节将指导你完成编辑 HTML(也称为模板)的过程。

  • product-list文件夹中,打开模板文件 product-list.component.html

  • <div>上添加一个结构型指令 *ngFor,如下所示。

src/app/product-list/product-list.component.html

<h2>Products</h2>

<div *ngFor="let product of products">
</div>

使用 *ngFor,会把这个 &lt;div&gt;针对列表中的每个产品进行复写。

With *ngFor, the &lt;div&gt;repeats for each product in the list.

结构型指令会通过添加、删除和操作元素来调整或重塑 DOM 结构。有关结构型指令的更多信息,请参见结构型指令。

src/app/product-list/product-list.component.html

<h2>Products</h2>

<div *ngFor="let product of products">

  <h3>
      {{ product.name }}
  </h3>

</div>

预览窗格将会更新,以显示列表中每个商品的名称。

Product names added to list

  • 为了让每个商品名称都能链接到商品详情,请围绕 product.name添加一个 &lt;a&gt;元素。

  • 使用 [ ]语法将标题设置为此产品的名称,如下所示:

src/app/product-list/product-list.component.html

<h2>Products</h2>

<div *ngFor="let product of products">

  <h3>
    <a [title]="product.name + ' details'">
      {{ product.name }}
    </a>
  </h3>

</div>

在预览窗格中,将鼠标悬停在产品名称上,可以查看所绑定的 name 属性值,该值是产品名加上单词 “details”。通过属性绑定 [ ]可以在模板表达式中使用属性值。

Product name anchor text is product name property

  • 添加产品说明。在 &lt;p&gt;元素上使用 *ngIf指令,以便 Angular 只让当前产品有描述 &lt;p&gt;

src/app/product-list/product-list.component.html

<h2>Products</h2>

<div *ngFor="let product of products">

  <h3>
    <a [title]="product.name + ' details'">
      {{ product.name }}
    </a>
  </h3>

  <p *ngIf="product.description">
    Description: {{ product.description }}
  </p>

</div>

现在,该应用将在列表中显示每个产品的名称和描述。请注意,最后一项产品没有描述段落。Angular 不会创建 &lt;p&gt;元素,因为此产品的 description 属性为空。

Product descriptions added to list

  • 添加一个按钮,以便用户可以共享产品。将按钮的 click事件绑定到 product-list.component.ts中的 share()方法。事件绑定要在此事件用一组圆括号 ( )括起来,就比如 &lt;button&gt;元素上的 (click)

src/app/product-list/product-list.component.html

<h2>Products</h2>

<div *ngFor="let product of products">

  <h3>
    <a [title]="product.name + ' details'">
      {{ product.name }}
    </a>
  </h3>

  <p *ngIf="product.description">
    Description: {{ product.description }}
  </p>

  <button type="button" (click)="share()">
    Share
  </button>

</div>

每个产品现在都有一个 “Share” 按钮。

Share button added for each product 单击 “Share” 按钮将触发一条通知,指出 “The product has been shared!”。

Alert box indicating product has been shared

在编辑模板时,你已经了解了 Angular 模板的一些最常用的功能。更多信息,请参阅组件和模板简介。

# 将数据传递给子组件

目前,产品列表中显示了每个产品的名称和描述。ProductListComponent还定义了一个 products属性,包含从 products.tsproducts数组导入的各个产品的数据。

下一步是创建一个新的通知功能,该功能会使用来自 ProductListComponent的产品数据。通知会检查产品的价格,如果价格大于 700 美元,则会显示 Notify Me按钮,当产品上市销售时,用户可以通过该按钮注册通知。

本节将引导你创建一个子组件 ProductAlertsComponent,该子组件可以从其父组件 ProductListComponent接收数据。

  • 点击当前终端上方的加号,新建一个终端,运行命令生成组件。

StackBlitz command to generate component

  • 在新终端中,通过运行以下命令生成一个名为 product-alerts的新组件。

ng generate component product-alerts

该生成器会为组件的三个部分创建初始文件:

  • product-alerts.component.ts

  • product-alerts.component.html

  • product-alerts.component.css

  • 打开 product-alerts.component.ts@Component()装饰器会指出它后面的类是组件。@Component()还会提供有关组件的元数据,包括其选择器、模板和样式。

src/app/product-alerts/product-alerts.component.ts

@Component({
  selector: 'app-product-alerts',
  templateUrl: './product-alerts.component.html',
  styleUrls: ['./product-alerts.component.css']
})
export class ProductAlertsComponent {

}

@Component()中的主要功能如下:

  • selectorapp-product-alerts)用于标识组件。按照惯例,Angular 组件选择器以前缀 app-开头,后跟组件名称。

  • 模板和样式文件名引用了组件的 HTML 和 CSS。

  • 这个 @Component()定义还导出了类 ProductAlertsComponent,该类会处理组件的功能。

  • 要将 ProductAlertsComponent设置为接收产品数据,请首先从 @angular/core中导入符号 Input

src/app/product-alerts/product-alerts.component.ts

import { Component, Input } from '@angular/core';
import { Product } from '../products';
  • ProductAlertsComponent类定义中,使用 @Input()装饰器定义一个名为 product的属性。@Input()装饰器指出此属性值要从本组件的父组件 ProductListComponent中传入。

src/app/product-alerts/product-alerts.component.ts

export class ProductAlertsComponent {

  @Input() product!: Product;

}
  • 打开 product-alerts.component.html并将占位符段落替换为 Notify Me按钮,如果产品价格超过 700 美元,就会出现此按钮。

src/app/product-alerts/product-alerts.component.html

<p *ngIf="product && product.price > 700">
  <button type="button">Notify Me</button>
</p>
  • 生成器会自动把 ProductAlertsComponent添加到 AppModule中,以便它能用于本应用的其它组件中。

src/app/app.module.ts

import { ProductAlertsComponent } from './product-alerts/product-alerts.component';

@NgModule({
  declarations: [
    AppComponent,
    TopBarComponent,
    ProductListComponent,
    ProductAlertsComponent,
  ],
  • 最后,要将 ProductAlertsComponent显示为 ProductListComponent的子级,请将 &lt;app-product-alerts&gt;元素添加到 product-list.component.html中。使用属性绑定将当前产品作为输入传给此组件。

src/app/product-list/product-list.component.html

<button type="button" (click)="share()">
  Share
</button>

<app-product-alerts
  [product]="product">
</app-product-alerts>

这个新的产品通知组件将产品作为产品列表中的输入。使用该输入,它将根据产品的价格显示或隐藏 Notify Me按钮。Phone XL 的价格超过了 700 美元,因此该产品上会显示 Notify Me按钮。

Product alert button added to products over $700

# 将数据传递到父组件

为了使 Notify Me按钮起作用,子组件需要通知并将数据传递给父组件。当用户单击 Notify MeProductAlertsComponent需要引发一个事件,并且 ProductListComponent需要响应此事件。

在新建组件时,Angular 生成器会包含一个空的 constructor()OnInit接口和 ngOnInit()方法。由于这些步骤不会使用它们,下列范例代码中都省略了它们,以求简洁。

  • product-alerts.component.ts中,从 @angular/core导入符号 OutputEventEmitter

src/app/product-alerts/product-alerts.component.ts

import { Component, Input, Output, EventEmitter } from '@angular/core';
import { Product } from '../products';
  • 在组件类中,使用 @Output()装饰器和 EventEmitter()的实例定义一个名为 notify的属性。使用 @Output()配置 ProductAlertsComponent,这会让 ProductAlertsComponentnotify属性的值发生变化时引发一个事件。

src/app/product-alerts/product-alerts.component.ts

export class ProductAlertsComponent {
  @Input() product: Product | undefined;
  @Output() notify = new EventEmitter();
}
  • product-alerts.component.html中,修改 Notify Me按钮,增加事件绑定,并调用 notify.emit()方法。

src/app/product-alerts/product-alerts.component.html

<p *ngIf="product && product.price > 700">
  <button type="button" (click)="notify.emit()">Notify Me</button>
</p>
  • 定义用户单击按钮时发生的行为。当子组件引发事件时,父组件 ProductListComponent(而不是 ProductAlertsComponent)会采取行动。在 product-list.component.ts中,定义一个 onNotify()方法,类似于 share()方法。

src/app/product-list/product-list.component.ts

export class ProductListComponent {

  products = [...products];

  share() {
    window.alert('The product has been shared!');
  }

  onNotify() {
    window.alert('You will be notified when the product goes on sale');
  }
}
  • 更新 ProductListComponent,以从 ProductAlertsComponent中接收数据。

product-list.component.html中,将 &lt;app-product-alerts&gt;绑定到产品列表组件的 onNotify()方法。&lt;app-product-alerts&gt;会显示 Notify Me按钮的内容。

src/app/product-list/product-list.component.html

<button type="button" (click)="share()">
  Share
</button>

<app-product-alerts
  [product]="product" 
  (notify)="onNotify()">
</app-product-alerts>
  • 单击 Notify Me按钮以触发一条通知,内容为:"You will be notified when the product goes on sale"。

Product alert notification confirmation dialog

有关组件之间的通信的更多信息,请参见组件交互。

# 下一步呢?

在本节中,你已经创建了一个应用,该应用会遍历数据,并让特性组件彼此通讯。

要继续探索 Angular 并开发此应用,请执行以下操作:

  • 继续进行应用内导航,以创建产品详情页。

  • 跳至部署以转为本地开发,或将你的应用部署到 Firebase 或你自己的服务器上。

Last Updated: 5/16/2023, 7:35:10 PM