1. 简介
构建内容
在此 Codelab 中,您将使用 Angular v14 构建一个野生动物图库应用。完成的应用将显示一组照片,还会提供一个发送消息表单,用于联系摄影师;此外,还会提供一个聊天窗口,用于了解照片中动物的有趣知识。
您使用 Angular v14 和新的独立组件功能构建应用中的所有内容。
对 Angular 框架和 Angular CLI 的所有引用均反映了 Angular v14。独立组件是 Angular v14 的预览版功能,因此您必须使用 Angular v14 创建全新的应用。独立组件提供了一种简化的 Angular 应用构建方式。独立组件、独立指令和独立管道旨在减少对 NgModules 的需求,从而简化创作体验。独立组件能够充分利用现有的 Angular 库生态系统。
这是您今天构建的应用。

学习内容
- 如何使用 Angular CLI 搭建新项目
- 如何使用 Angular 独立组件来简化 Angular 应用的开发
- 如何创建独立组件;即如何构建界面并添加一些业务逻辑
- 如何使用独立组件引导应用
- 如何延迟加载独立组件
- 如何使用 Dialogflow Messenger 在独立组件中嵌入聊天对话
- 如何使用 Google Cloud CLI (gcloud) 将 Angular 应用部署到 Google Cloud App Engine
所需条件
- Gmail 或 Google Workspace 账号
- 具备以下主题的基础知识
- HTML。如何创建元素。
- CSS 和 Less。如何使用 CSS 选择器和创建样式定义文件。
- TypeScript 或 JavaScript。如何与 DOM 结构互动。
- Git 和 GitHub。如何创建代码库分支并克隆代码库。
- 命令行界面,例如
bash或zsh。如何浏览目录和运行命令。
2. 环境设置
设置本地环境
如需完成此 Codelab,您必须在本地计算机上安装以下软件。
- Node.js 的有效 LTS 或维护 LTS 版本。用于安装 Angular 框架和 Angular CLI。
如需验证本地计算机上的 Node.js 版本,请从命令行窗口运行以下节点版本
受 Angular 支持
14.15 或更高版本
支持
16.10 或更高版本
支持
18.1.0
不支持
node命令。node -v
- 代码编辑器或 IDE。用于打开和修改文件。Visual Studio Code 或您选择的其他代码编辑器。
安装 Angular CLI
配置完所有依赖项后,请从命令行窗口运行以下 npm 命令,以安装 Angular CLI。
npm install --global @angular/cli
如需确认配置是否正确,请从命令行运行以下 Angular 命令。
ng version
如果 Angular 命令成功完成,您应该会收到类似于以下屏幕截图的消息。

源代码和图片
您将从头开始创建整个应用,而本 Codelab 将逐步为您提供帮助。请注意,GitHub 代码库包含最终代码。如果您遇到困难,请查看最终代码和图库页面上显示的图片。
下载源代码。
- 在浏览器中,前往以下页面。
https://github.com/angular/codelabs/tree/standalone-components - 在命令行窗口中,创建代码库分支并克隆代码库。
在下一步中,构建您的照片库应用。
3. 创建新应用
如需创建初始启动器应用,请完成以下操作。
使用 Angular CLI 创建新工作区。如需详细了解 Angular CLI 和 Angular 框架,请访问 angular.io。
创建新项目
在命令行窗口中,完成以下操作。
- 输入以下 Angular 命令以创建名为
photo-gallery-app的新 Angular 项目。ng new photo-gallery-app
- 在每个提示处,接受默认选择。Angular 框架会安装所需的软件包和依赖项。此过程可能需要几分钟的时间。
Angular CLI 完成后,您将获得一个新的 Angular 工作区和一个可直接运行的简单应用。
您的新应用采用与标准 Angular 应用类似的结构。对于此 Codelab,新应用中的 NgModule 是多余的。
移除应用模块
如需移除应用模块,请完成以下操作。
- 前往新
photo-gallery-app项目目录中的src/app目录。 - 删除
app.module.ts文件。
删除应用模块后,您的应用中将没有任何模块。您的应用只有一个组件,即应用组件。您必须将该组件声明为独立组件。
声明独立组件
在代码编辑器中,完成以下操作。
- 前往新
photo-gallery-app项目目录中的src/app目录。 - 打开
app.component.ts文件。 - 将以下参数和值添加到您的装饰器列表中。
standalone: trueapp.component.ts文件应与以下代码示例非常相似。import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], standalone: true }) export class AppComponent { title = 'photo-gallery-app'; } - 保存
app.component.ts文件。
编译新的独立应用
在命令行窗口中,完成以下操作。
- 前往新的
photo-gallery-app项目目录 - 输入以下 Angular 命令以编译新应用。
ng serve
您的应用应该无法编译。别担心,您只需再修正几个问题即可。
使用 bootstrapApplication API
如需允许应用在没有 NgModule 的情况下运行,您必须使用独立组件作为根组件,方法是使用 bootstrapApplication API。
移除对应用模块的引用
在代码编辑器中,完成以下操作。
- 前往新
photo-gallery-app项目目录中的src目录 - 打开
main.ts文件。 - 移除以下导入代码,因为您不再有应用模块。
import { AppModule } from './app/app.module'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; - 移除以下引导加载程序代码,因为您不再有应用模块。
platformBrowserDynamic().bootstrapModule(AppModule) .catch(err => console.error(err));main.ts文件应与以下代码示例一致。import { enableProdMode } from '@angular/core'; import { environment } from './environments/environment'; if (environment.production) { enableProdMode(); }
添加 bootstrapApplication 组件
在代码编辑器中,完成以下操作。
- 前往新
photo-gallery-app项目目录中的src目录。 - 打开
main.ts文件。 - 从
@angular/platform-browser服务中导入bootstrapApplication组件。import { bootstrapApplication } from '@angular/platform-browser'; - 添加以下代码以引导启动应用。
bootstrapApplication(AppComponent).catch(err => console.error(err)); - 导入组件和必需的库。
import { AppComponent } from './app/app.component';main.ts文件应与以下代码示例一致。import { enableProdMode } from '@angular/core'; import { bootstrapApplication } from '@angular/platform-browser'; import { AppComponent } from './app/app.component'; import { environment } from './environments/environment'; if (environment.production) { enableProdMode(); } bootstrapApplication(AppComponent).catch(err => console.error(err));
添加了路由器和通用模块
如需使用 Router 和其他常见模块功能,您必须将每个模块直接导入到组件中。
在代码编辑器中,完成以下操作。
- 前往新
photo-gallery-app项目目录中的src/app目录。 - 打开
app.component.ts文件。 - 将必需的模块导入到组件中。
import { CommonModule } from '@angular/common'; import { RouterModule } from '@angular/router'; - 在组件中添加导入。
imports: [CommonModule, RouterModule],app.component.ts文件应与以下代码示例一致。import { Component } from '@angular/core'; import { CommonModule } from '@angular/common'; import { RouterModule } from '@angular/router'; @Component({ selector: 'app-root', imports: [CommonModule, RouterModule], templateUrl: './app.component.html', styleUrls: ['./app.component.css'], standalone: true }) export class AppComponent { title = 'photo-gallery-app'; } - 保存
app.component.ts文件。
编译并运行新的独立应用
在命令行窗口中,完成以下操作。
- 前往新的
photo-gallery-app项目目录。 - 输入以下 Angular 命令以编译并运行应用,并打开 Web 服务器。您可能需要在运行应用之前关闭 IDE,以消除所有编译错误。
ng serve
您的开发服务器应在端口 4200 上运行。所有之前的错误都应消失,并且编译应成功。非常棒!您已成功创建了一个无需模块且具有独立组件的 Angular 应用。
- 接下来,您将美化应用以显示一些照片。
4. 显示照片
您的新应用设计为图库,应显示一些照片。
组件是 Angular 应用的核心构建块。组件有 3 个主要方面。
- 模板的 HTML 文件
- 用于样式的 CSS 文件
- 用于应用行为的 TypeScript 文件
将照片移至您的应用
这些图片包含在您之前从 GitHub 下载的应用中。
- 前往 GitHub 项目的
src/assets目录。 - 将文件复制并粘贴到
photo-gallery-app项目目录中的analogue目录中。
创建 HTML 模板
app.component.html 文件是与 AppComponent 组件关联的 HTML 模板文件。
在代码编辑器中,完成以下操作。
- 前往新
photo-gallery-app项目目录中的src/app目录。 - 打开
app.component.html文件。 - 删除所有现有的 HTML。
- 复制并粘贴以下代码示例中的 HTML。
<article> <h1>Above and below the Ocean</h1> <h2>A taste of the Australia and Galapagos Wildlife, meet my friends!</h2> <section> <section class="row"> <div class="column"> <img src="/assets/49412593648_8cc3277a9c_c.jpg"> <img src="/assets/49413271167_22a504c3fa_w.jpg"> <img src="/assets/47099018614_5a68c0195a_w.jpg"> </div> <div class="column"> <img src="/assets/41617221114_4d5473251c_w.jpg"> <img src="/assets/47734160411_f2b6ff8139_w.jpg"> <img src="/assets/46972303215_793d32957f_c.jpg"> </div> <div class="column"> <img src="/assets/45811905264_be30a7ded6_w.jpg"> <img src="/assets/44718289960_e83c98af2b_w.jpg"> <img src="/assets/46025678804_fb8c47a786_w.jpg"> </div> </section> </section> </article - 保存
app.component.html文件。
创建样式定义文件
在代码编辑器中,完成以下操作。
- 前往新
photo-gallery-app项目目录中的src目录。 - 打开
styles.css文件。 - 复制并粘贴以下代码示例中的 CSS。
article { display: flex; justify-content: center; align-items: center; flex-direction: column; font-family: 'Raleway'; } h1 { color: #4479BA; text-align: center; font-size: xx-large; } h2 { color: rgb(121, 111, 110); text-align: center; } .row { display: flex; flex-wrap: wrap; padding: 0 4px; } /* Create four equal columns that sits next to each other */ .column { flex: 25%; padding: 0 4px; } .column img { margin-top: 8px; vertical-align: middle; width: 100%; } .link_button { -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; border: solid 1px #20538D; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.4); -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4), 0 1px 1px rgba(0, 0, 0, 0.2); -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4), 0 1px 1px rgba(0, 0, 0, 0.2); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4), 0 1px 1px rgba(0, 0, 0, 0.2); background: #4479BA; color: #FFF; padding: 8px 12px; text-decoration: none; margin-top: 50px; font-size: large; } @media screen and (max-width: 800px) { .column { flex: 50%; max-width: 50%; } } @media screen and (max-width: 600px) { .column { flex: 100%; max-width: 100%; } } - 保存
styles.css文件
更新索引文件
在代码编辑器中,完成以下操作。
- 前往新
photo-gallery-app项目目录中的src目录。 - 打开
index.html文件。 - 添加
Raleway字体,以允许所有网页继承该字体。<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Raleway"> - 保存
index.html文件。 - 保存代码并检查浏览器。在开发服务器运行的情况下,您保存更改后,浏览器中会显示相应更改。
- 接下来,您将创建一个新的独立组件,用于发送反馈和与 Jimbo 对话。继续学习本 Codelab,详细了解 Jimbo。
5. 添加新的独立组件
正如您目前所见,独立组件通过减少对 NgModule 的需求,提供了一种简化的 Angular 应用构建方式。在以下部分中,您将创建一个新的独立组件,让用户能够发送反馈并与虚拟客服聊天。
创建新的独立组件
如需创建此新组件,请再次使用 Angular CLI。
在命令行窗口中,完成以下操作。
- 前往新的
photo-gallery-app项目目录。 - 输入以下 Angular 命令以创建名为
feedback-and-chat的新组件。 下表介绍了该命令的各个部分。ng generate component feedback-and-chat --standalone
部分
详细信息
ng定义了 Angular 框架的所有 Angular CLI 命令
generate component为新组件创建基架
feedback-and-chat组件的名称
--standalone告知 Angular 框架创建独立组件
导入新的独立组件
如需使用新的独立组件,您必须先将其添加到 app.components.ts 文件中的 imports 数组。
这是一个独立组件,因此您只需像导入模块一样导入它。
在代码编辑器中,完成以下操作。
- 前往新
photo-gallery-app项目目录中的src/app目录。 - 打开
app.component.ts文件。 - 导入新的独立组件。
import { FeedbackAndChatComponent } from './feedback-and-chat/feedback-and-chat.component'; - 更新组件中的导入项。
imports: [CommonModule, RouterModule, FeedbackAndChatComponent],app.component.ts文件应与以下代码示例一致。import { CommonModule } from '@angular/common'; import { Component } from '@angular/core'; import { RouterModule } from '@angular/router'; import { FeedbackAndChatComponent } from './feedback-and-chat/feedback-and-chat.component'; @Component({ selector: 'app-root', imports: [CommonModule, RouterModule, FeedbackAndChatComponent], templateUrl: './app.component.html', styleUrls: ['./app.component.css'], standalone: true }) export class AppComponent { title = 'photo-gallery-app'; } - 保存
app.component.ts文件。
延迟加载组件
从急切加载范式切换到延迟加载范式,在这种范式中,代码不会发送到客户端,直到您需要它时才会发送。延迟加载是一种很好的方法,可缩短网页加载时间、提高性能并改善用户体验。路由器会处理延迟加载,这对于 ngModule 和独立组件来说是相同的。
更新与应用组件关联的 HTML 模板
如需延迟加载独立组件,请向界面添加一个按钮,该按钮仅在用户选择时激活组件。
在代码编辑器中,完成以下操作。
- 前往新
photo-gallery-app项目目录中的src/app目录。 - 打开
app.component.html文件。 - 滚动到文件末尾,然后在关闭
article元素之前添加以下代码示例。<a class="link_button" routerLink="feedback-and-chat">Find out more about these guys!</a> <router-outlet></router-outlet> app.component.html文件应与以下代码示例一致。<article> <h1>Above and below the Ocean</h1> <h2>A taste of the Australia and Galapagos Wildlife, meet my friends!</h2> <section> <section class="row"> <div class="column"> <img src="/assets/49412593648_8cc3277a9c_c.jpg"> <img src="/assets/49413271167_22a504c3fa_w.jpg"> <img src="/assets/47099018614_5a68c0195a_w.jpg"> </div> <div class="column"> <img src="/assets/41617221114_4d5473251c_w.jpg"> <img src="/assets/47734160411_f2b6ff8139_w.jpg"> <img src="/assets/46972303215_793d32957f_c.jpg"> </div> <div class="column"> <img src="/assets/45811905264_be30a7ded6_w.jpg"> <img src="/assets/44718289960_e83c98af2b_w.jpg"> <img src="/assets/46025678804_fb8c47a786_w.jpg"> </div> </section> </section> <a class="link_button" routerLink="feedback-and-chat">Find out more about these guys!</a> <router-outlet></router-outlet> </article>- 保存
app.component.html文件。
配置路线
在代码编辑器中,完成以下操作。
- 前往新
photo-gallery-app项目目录中的src目录。 - 打开
main.ts文件 - 导入
provideRouter方法和 Routes 模块。Angular v 14.2.0 引入了一种新的 provideRouter 方法,可用于为应用配置一组路由。import { provideRouter, Routes } from '@angular/router'; - 复制以下代码段并将其粘贴到导入语句和
if语句之间。const routes = [ { path: 'feedback-and-chat', loadComponent: () => import('./app/feedback-and-chat/feedback-and-chat.component').then(c => c.FeedbackAndChatComponent), } ] - 复制并粘贴以下代码段,然后替换
bootstrapApplication方法。bootstrapApplication(AppComponent, { providers: [ provideRouter(routes) ] }).catch(err => console.error(err));main.ts文件应与以下代码示例一致。import { enableProdMode } from '@angular/core'; import { bootstrapApplication } from '@angular/platform-browser'; import { provideRouter, Routes } from '@angular/router'; import { AppComponent } from './app/app.component'; import { environment } from './environments/environment'; const routes = [ { path: 'feedback-and-chat', loadComponent: () => import('./app/feedback-and-chat/feedback-and-chat.component').then(c => c.FeedbackAndChatComponent), } ] if (environment.production) { enableProdMode(); } bootstrapApplication(AppComponent, { providers: [ provideRouter(routes) ] }).catch(err => console.error(err)); - 保存
main.ts文件。
使用 Chrome 开发者工具进行编译和查看
使用 Chrome 开发者工具查看 Angular 框架如何延迟加载组件。
在命令行窗口中,完成以下操作。
- 前往新的
photo-gallery-app项目目录。 - 输入以下 Angular 命令以编译并运行应用,并打开 Web 服务器。
您的开发服务器应在端口ng serve
4200上运行。
在浏览器中,完成以下操作。
- 前往以下页面。
http://localhost:4200 - 打开 Chrome 开发者工具,然后选择网络标签页。
- 刷新页面以显示多个文件,但不显示
feedback-and-chat组件。界面应与以下屏幕截图一致。
- 选择 Find out more about these guys! 按钮以路由到独立组件。日志应表明,仅当您点击完整路由器时,系统才会加载该组件。向下滚动到列表末尾,检查组件是否已加载。界面应与以下屏幕截图一致。

6. 添加表单的界面
发送反馈表单包含三个输入界面字段和一个位于底部的按钮。这三个输入界面字段分别是全名、发件人电子邮件地址和评论。
为了支持界面,请在 input 元素中添加一个 formControlName 属性,该属性会绑定到与三个输入界面字段中的每个字段相关联的每个 contactForm 表单控件。
将表单添加到 HTML 模板
向界面添加表单,以便用户发送反馈。
在代码编辑器中,完成以下操作。
- 找到
feedback-and-chat.component.html文件。 - 移除现有 HTML。
- 复制并粘贴以下代码示例中的 HTML。
<article> <h2>Send me a message or use the chat below to learn some cool facts of the animals in the photos</h2> <section class="container"> <form ngNativeValidate [formGroup]="contactForm" (ngSubmit)="onSubmit()"> <div class="row" *ngIf="showMsg"> <div class="row"> <p> <strong>Thanks for your message!</strong> </p> </div> </div> <div class="row"> <div class="col-25"> <label for="name">Full Name</label> </div> <div class="col-75"> <input type="text" id="fname" placeholder="Your name.." formControlName="fullname" required> </div> </div> <div class="row"> <div class="col-25"> <label for="lemail">Email</label> </div> <div class="col-75"> <input type="text" id="lemail" placeholder="Your email.." formControlName="email" required> </div> </div> <div class="row"> <div class="col-25"> <label for="comments">Comments</label> </div> <div class="col-75"> <textarea id="subject" formControlName="comments" placeholder="Write something.." style="height:200px" required></textarea> </div> </div> <div class="row"> <button type="submit" class="submit">Submit</button> </div> </form> </section> </article> - 保存
feedback-and-chat.component.html文件。
更新表单的样式文件
在代码编辑器中,完成以下操作。
- 找到
feedback-and-chat.component.css文件。 - 复制并粘贴以下代码示例中的 CSS。
/* Style inputs, select elements and textareas */ input[type=text], select, textarea{ width: 100%; padding: 12px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; resize: vertical; } /* Style the label to display next to the inputs */ label { padding: 12px 12px 12px 0; display: inline-block; } /* Style the submit button */ button { background-color: #4479BA; color: white; padding: 12px 20px; border: none; border-radius: 4px; cursor: pointer; float: right; font-size: medium; font-family: 'Raleway'; } /* Style the container */ .container { border-radius: 5px; background-color: #f2f2f2; padding: 20px; width: 100%; } /* Floating column for labels: 25% width */ .col-25 { float: left; width: 25%; margin-top: 6px; } /* Floating column for inputs: 75% width */ .col-75 { float: left; width: 75%; margin-top: 6px; } /* Clear floats after the columns */ .row:after { content: ""; display: table; clear: both; } /* Responsive layout - when the screen is less than 600px wide, make the two columns stack on top of each other instead of next to each other */ @media screen and (max-width: 600px) { .col-25, .col-75, input[type=submit] { width: 100%; margin-top: 0; } } - 保存
feedback-and-chat.component.css文件。
编译表单的界面更新
在命令行窗口中,完成以下操作。
- 前往新的
photo-gallery-app项目目录。 - 输入以下 Angular 命令以编译并运行应用,并打开 Web 服务器。
您的应用应无法编译。别担心,您只需绑定表单即可。ng serve
- 目前,请查看以下内容。
- 您可以使用
formGroup属性绑定将contactForm绑定到form元素,并使用ngSubmit事件绑定 FormGroup指令会监听form元素发出的提交事件。然后,FormGroup指令会发出ngSubmit事件,您可以将其绑定到onSubmit回调函数。- 在后面的步骤中,您将在
feedback-and-chat.component.ts文件中实现onSubmit回调函数
- 您可以使用
- 接下来,您将绑定表单。
7. 向表单添加事件处理功能
发送反馈表单的界面已完成,但缺少互动。使用表单处理用户输入是许多常见应用的基础。
在实际应用场景中,您需要实现业务逻辑才能完成以下操作。
- 解析与组件关联的渲染 DOM 结构中的用户输入。
- 验证用户输入,包括使用验证码或类似机制来避免机器人发送垃圾信息。
- 向指定电子邮件地址发送电子邮件。
- 向用户显示一条友好的消息。
在此 Codelab 中,您只需实现以下操作。
- 解析与组件关联的渲染 DOM 结构中的用户输入。
- 向用户显示一条友好的消息。
您应该挑战自己的技能,并实现所有四项操作。
将发送消息表单模型添加到组件
在组件类中创建并添加“发送反馈”表单模型。表单模型决定了表单的状态。FormBuilder 服务提供了用于创建界面控件的便捷方法。
在代码编辑器中,完成以下操作。
- 找到
feedback-and-chat.component.ts文件。 - 从
@angular/forms软件包中导入FormBuilder服务和ReactiveModule模块。此服务提供了用于生成控件的便捷方法。在下一步中,我们将利用inject函数,因此还需要从@angular/core中导入该函数。import { Component, inject, OnInit } from '@angular/core'; import { FormBuilder, ReactiveFormsModule } from '@angular/forms'; - 导入
ReactiveFormsModule模块。imports: [CommonModule,ReactiveFormsModule], - 移除了以下构造函数。
constructor() { } - 通过类签名正下方的
inject函数注入FormBuilder服务。 使用private formBuilder = inject(FormBuilder);FormBuilder服务中的group方法创建表单模型,以便收集用户的姓名、电子邮件地址和评论。 - 创建新的
contactForm属性,并使用group方法将其设置为表单模型。表单模型包含name、email和comments字段。 定义一个contactForm = this.formBuilder.group({ fullname: '', email: '', comments: '' });onSubmit方法来处理表单。在实际场景中,onSubmit方法允许用户通过发送到指定电子邮件地址的电子邮件消息向摄影师提交反馈消息。在此 Codelab 中,您将显示用户输入的内容,使用reset方法重置表单,并显示一条用户友好的成功消息。 - 添加新的
onSubmit方法,并在初始化showMsg变量后将其设置为true。showMsg: boolean = false; onSubmit(): void { console.log('Your feedback has been submitted', this.contactForm.value); this.showMsg = true; this.contactForm.reset(); }feedback-and-chat.component.ts文件应与以下代码示例一致。import { Component, inject, OnInit } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormBuilder, ReactiveFormsModule } from '@angular/forms'; @Component({ selector: 'app-feedback-and-chat', standalone: true, imports: [CommonModule, ReactiveFormsModule], templateUrl: './feedback-and-chat.component.html', styleUrls: ['./feedback-and-chat.component.css'] }) export class FeedbackAndChatComponent { showMsg: boolean = false; private formBuilder = inject(FormBuilder); contactForm = this.formBuilder.group({ fullname: '', email: '', comments: '' }); ngOnInit(): void { } onSubmit(): void { console.log('Your feedback has been submitted', this.contactForm.value); this.showMsg = true; this.contactForm.reset(); } } - 保存
feedback-and-chat.component.ts文件。
编译并显示“发送反馈”表单模型
在命令行窗口中,完成以下操作。
- 前往新的
photo-gallery-app项目目录。 - 输入以下 Angular 命令以编译并运行应用,并打开 Web 服务器。
ng serve
- 您的开发服务器应在端口
4200上运行。
在浏览器中,完成以下操作。
- 前往以下页面。
http://localhost:4200 - 打开 Chrome 开发者工具,然后选择控制台标签页。
- 在全名、电子邮件地址和评论文本框中输入任意值。
- 选择提交按钮。页面上应会显示一条成功消息。
- 验证值是否显示在控制台标签页中。您的屏幕应与以下屏幕截图一致。
您已成功实现代码,以向组件界面添加发送消息表单并解析用户输入。 - 接下来,您将嵌入一个聊天对话框,以便应用访问者与 Jimbo 对话。Jimbo 是一只考拉,你可以从它那里了解一些有关野生动物的有趣知识。
8. 添加聊天对话框
利用在对话界面(例如 Dialogflow CX 或类似平台)方面的经验。Dialogflow CX 代理是负责与人类同时对话的虚拟客服。它是一种自然语言理解模块,能够识别人类语言的细微差别,并将对话过程中的最终用户文本或音频转换为应用和服务可以理解的结构化数据。
我们已为您创建了一个示例虚拟客服,您可以直接使用。在本实验中,您需要向独立组件添加聊天对话,以便应用用户与聊天机器人互动。对于此要求,您将利用 Dialogflow Messenger,这是一种预建的集成,可提供可自定义的对话窗口。打开时,聊天对话框会显示在屏幕右下方,并触发代理的默认欢迎意图。聊天机器人向用户问好并开始对话。
以下实现会与用户分享有关野生动物的趣闻。其他虚拟客服实现方案可能能够满足客户的复杂使用情形(例如人类呼叫中心客服人员)。许多公司都使用虚拟客服作为与公司网站进行通信的主要渠道。
将 Dialogflow Messenger 添加到组件
与表单类似,聊天对话框应仅在加载独立组件时显示。
在代码编辑器中,完成以下操作。
- 找到
feedback-and-chat.component.ts文件。 - 将以下代码示例中的
df-messenger元素复制并粘贴到网页中的任意位置。 选择 Dialogflow Messenger 集成时,Dialogflow 会为<df-messenger agent-id="762af666-79f7-4527-86c5-9ca06f72c317" chat-title="Chat with Jimbo!" df-cx="true" intent="messanger-welcome-event" language-code="en" location="us-central1"></df-messenger>df-messenger元素生成属性。属性
详细信息
agent-id
预先填充。指定 Dialogflow 代理的唯一标识符。
chat-title
预先填充。指定要在聊天对话框顶部显示的内容。最初预填充了智能体的名称,但您应该自定义该名称。
df-cx
表示与 CX 代理互动。将值设置为
true。intent
指定用于在聊天对话框打开时触发第一个意图的自定义事件。
language-code
指定第一个意图的默认语言代码。
地理位置
指定部署代理的区域。
- 保存
feedback-and-chat.component.ts文件。
显示“发送反馈”表单模型
在命令行窗口中,完成以下操作。
- 前往新的
photo-gallery-app项目目录。 - 输入以下 Angular 命令来编译应用。
您的应用应无法编译。命令行应显示以下错误消息。ng serve

- 接下来,添加自定义架构。
向独立组件添加自定义架构
df-messanger 元素不是已知元素。它是一个自定义 Web 组件。Angular 框架的错误消息表明,您必须向两个独立组件添加 CUSTOM_ELEMENTS_SCHEMA,才能抑制该消息。
在代码编辑器中,完成以下操作。
- 找到
feedback-and-chat.component.ts文件。 - 导入
CUSTOM_ELEMENTS_SCHEMA架构。import { Component, CUSTOM_ELEMENTS_SCHEMA, inject, OnInit } from '@angular/core'; - 将
CUSTOM_ELEMENTS_SCHEMA添加到架构列表中。schemas: [CUSTOM_ELEMENTS_SCHEMA]feedback-and-chat.component.ts文件应与以下代码示例一致。import { Component, CUSTOM_ELEMENTS_SCHEMA, inject, OnInit } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormBuilder, ReactiveFormsModule } from '@angular/forms'; @Component({ selector: 'app-feedback-and-chat', standalone: true, imports: [CommonModule,ReactiveFormsModule], templateUrl: './feedback-and-chat.component.html', styleUrls: ['./feedback-and-chat.component.css'], schemas: [CUSTOM_ELEMENTS_SCHEMA] }) ... - df-messanger 网络组件需要一个 JavaScript,该 JavaScript 仅在加载反馈和聊天组件时注入。为此,我们将向 ngOnInit() 方法添加相关代码,以加载激活
元素所需的聊天脚本。ngOnInit() { // Load the chat script, which activates the `<df-messenger>` element. const script = document.createElement('script'); script.async = true; script.src = 'https://www.gstatic.com/dialogflow-console/fast/messenger-cx/bootstrap.js?v=1'; document.head.appendChild(script); } - 保存
feedback-and-chat.component.ts文件。
编译并显示更新后的聊天对话框
在命令行窗口中,完成以下操作。
- 前往新的
photo-gallery-app项目目录。 - 输入以下 Angular 命令以编译并运行应用,并打开 Web 服务器。
您的开发服务器应在端口ng serve
4200上运行。
在浏览器中,完成以下操作。
- 前往以下页面。
页面底部应会显示聊天图标。http://localhost:4200 - 选择该图标并与 Jimbo 互动。Jimbo 会提供有趣的动物知识。

- 应用可完全正常运行。
9. 将应用部署到 Google App Engine
应用正在本地计算机上运行。在此 Codelab 的下一步也是最后一步中,您需要将应用部署到 Google App Engine。
如需详细了解 Google App Engine,请参阅 App Engine。
为 Google App Engine 设置环境
如果您已满足以下所有条件,请跳过后续步骤,直接部署应用。
- 创建了包含 App Engine 的云项目
- 已启用 Cloud Build API
- 安装了 Google Cloud CLI
完成以下操作。
- 登录您的 Gmail 或 Google Workspace 账号。如果您没有 Google 账号,请创建 Google 账号。
- 在 Cloud 控制台中启用结算功能,以便您可以使用 Cloud 资源和 API。如需了解详情,请参阅创建、修改或关闭自助 Cloud Billing 账号。
- 创建 Google Cloud 项目,以存放您的 App Engine 应用资源和其他 Google Cloud 资源。如需了解详情,请参阅创建和管理项目。
- 在 Cloud 控制台中启用 Cloud Build API。如需了解详情,请参阅启用对 API 的访问权限。
- 安装 Google Cloud CLI 和 gcloud 命令行工具。如需了解详情,请参阅安装 gcloud CLI。
- 初始化 Google Cloud CLI,并确保 gcloud 已配置为使用您要部署到的 Google Cloud 项目。如需了解详情,请参阅初始化 gcloud CLI。
构建独立应用
在命令行窗口中,完成以下操作。
- 前往新的
photo-gallery-app项目目录。 - 输入以下 Angular 命令,以编译并创建可用于生产用途的应用版本。
ng build
应用的正式版将在 photo-gallery-app 项目目录的 dist 子目录中创建。
10. 使用 Express.js 框架部署应用
本 Codelab 中的示例代码使用 Express.js 框架来处理 HTTP 请求。您可以使用自己喜欢的 Web 框架。
安装 Express.js 框架
在命令行窗口中,完成以下操作。
- 输入以下命令以安装 Express.js 框架。
npm install express --save
配置 Web 服务器
在代码编辑器中,完成以下操作。
- 前往新的
photo-gallery-app项目目录。 - 创建新的
server.js文件。 - 复制并粘贴以下代码。
const express = require("express"); const path = require("path"); // Running PORT is set automatically by App Engine const port = process.env.PORT || 3000; const app = express(); const publicPath = path.join(__dirname, "/dist/photo-gallery-app"); app.use(express.static(publicPath)); app.get("*", (req, res) => { res.sendFile(path.join(__dirname + "/dist/photo-gallery-app/index.html")); }); app.listen(port, () => { console.log(`Server is up on ${port}`); }); - 保存
server.js文件。
附加 Web 服务器
在代码编辑器中,完成以下操作。
- 前往新的
photo-gallery-app项目目录。 - 打开
package.json文件。 - 修改启动命令,以运行
server.js文件中的节点。"name": "photo-gallery-app", "version": "0.0.0", "scripts": { "ng": "ng", "start": "node server.js", "build": "ng build", "watch": "ng build --watch --configuration development", "test": "ng test" },start属性是应用的入口点。 - 保存
package.json文件。
配置 App Engine
在代码编辑器中,完成以下操作。
- 前往新的
photo-gallery-app项目目录。 - 创建新的
app.yaml文件。 - 复制并粘贴以下代码。
runtime: nodejs16 service: defaultapp.yaml文件中的信息指定了 App Engine 的配置。您只需指定运行时和服务。 - 保存
app.yaml文件。
更新 gcloud 忽略列表
为确保不上传 node_modules 目录,请创建 .gcloudignore 文件。.gcloudignore 文件中列出的文件不会上传。
在代码编辑器中,完成以下操作。
- 前往新的
photo-gallery-app项目目录。 - 创建新的
.gcloudignore文件。 - 复制并粘贴以下代码。
# This file specifies files that are *not* uploaded to Google Cloud # using gcloud. It follows the same syntax as .gitignore, with the addition of # "#!include" directives (which insert the entries of the given .gitignore-style # file at that point). # # For more information, run: # $ gcloud topic gcloudignore # .gcloudignore # If you would like to upload your .git directory, .gitignore file or files # from your .gitignore file, remove the corresponding line # below: .git .gitignore # Node.js dependencies: node_modules/ - 保存
.gcloudignore文件。
初始化应用
在部署应用之前,请先使用您的项目初始化应用,然后选择关联的区域。
在命令行窗口中,完成以下操作。
- 前往新的
photo-gallery-app项目目录。 - 输入以下命令以初始化应用。
gcloud app create --project=[YOUR_PROJECT_ID]
- 在提示中,选择您希望自己的 App Engine 应用所在的区域。
部署应用
在命令行窗口中,完成以下操作。
- 前往新的
photo-gallery-app项目目录。 - 输入以下命令以部署应用。
gcloud app deploy --project=[YOUR_PROJECT_ID]
- 在提示符处确认操作。gcloud 部署命令成功完成后,系统会显示一个用于访问应用的网址。
- 输入以下命令,在浏览器中打开新标签页。
gcloud app browse

11. 恭喜
恭喜!您使用 Angular v14 创建了一个示例图库,并成功将其部署在 App Engine 上。
您尝试了独立组件功能和延迟加载。您构建了一个基于表单的发送消息功能,用于提供反馈和评论。您还成功使用 Dialogflow Messenger 添加了与 Dialogflow CX 虚拟客服的聊天对话。太棒了!
后续步骤
现在,您已完成基本应用,接下来请使用以下想法来改进它。
- 该表单实际上并未发送反馈,请对其进行重构以添加发送电子邮件的业务逻辑。
- 在实际应用场景中,您应验证用户输入,并添加验证码或类似机制,以避免机器人发送垃圾内容
- 创建新代理并了解如何在 Dialogflow CX 中设计对话流程
继续尝试使用 Angular 框架,尽情享受其中的乐趣。
清理并删除您的云项目
您可以保留 Cloud 项目,也可以删除该项目,以停止对该项目中使用的所有资源计费。
在浏览器中,完成以下操作。