想学习 Angular 吗?Dan Wahlin 为我们准备了 33 节免费课程!
根据2018 年 Stack Overflow 开发者调查, Angular 是专业开发者中最受欢迎的框架/库之一。因此,学习它可以大大增加你获得 Web 开发者职位的机会。
这就是为什么我们与该框架最著名的专家之一合作,并在 Scrimba创建免费的 Angular 课程。
Dan Wahlin是一位 Google 开发者专家,曾为业内一些大型企业提供培训、架构和开发服务,并创建了 Udemy 和 Pluralsight 上一些最受欢迎的培训课程。他也是全球开发者大会的常客演讲嘉宾。
在本课程中,Dan 将指导您使用 TypeScript 创建您的第一个 Angular 应用。完成本课程后,您将获得宝贵的技能。
现在让我们看看课程是如何构成的!
第 1 部分:课程概述
在介绍视频中,Dan 概述了课程内容、Angular 的关键方面以及课程的布局。他还会简单介绍一下他的背景,以便您在开始编写新应用的代码之前熟悉他。
第 2 部分:应用程序概述
在本部分中,Dan 将带我们简要了解即将构建的应用。它旨在让我们专注于 Angular 的关键构建块。通过创建一个显示客户数据及其订单的应用,我们将深入学习 Angular 的关键方面,例如组件、模块、服务和路由。此外,在课程中,我们还将学习每个应用都具备的强大功能,例如排序和过滤。
第 3 部分:Angular CLI
在本部分中,我们将学习使用 Angular CLI(命令行界面)工具的基础知识并介绍基本命令:
ng --version
ng --help
ng new my-app-name
ng generate [component | directive | pipe | service | class | interface | enum | guard]
ng build
ng serve
ng lint
ng tests
例如,ng --new my-app-name
将为我们创建一个新的空白 Angular 应用程序,我们可以使用它ng -generate
来创建应用程序的各个部分。
ng build
将为我们构建一切,甚至ng serve -o
将启动开发服务器以及打开浏览器窗口供我们查看我们的应用程序。
第 4 部分:项目文件概述
在本课程视频中,Dan 对用于生成空白 Angular 应用程序的 CLI 命令进行了基本概述,并快速概述了我们的应用程序文件夹中的配置文件(如tslint
、tsconfig
和 )protractor
。
第五部分:总体情况
在这里,我们学习了一个有用的抽象概念:组件类似于乐高积木——我们先构建组件,然后将它们拼凑在一起,构成一个应用程序。我们还快速回顾了 JavaScript 语言家族,并了解了 TypeScript 的适用范围。
Dan 为我们提供了一个很好的心理模型,用于在使用 Angular 时思考我们的代码,以便我们可以想象它的全部内容。
第 6 部分:组件和模块 - 概述
如果没有抽象出来,Angular 代码的图表可能看起来像这样。
组件由代码和 HTML 模板组成,它可以有一个选择器,因此我们可以在 HTML 中调用它。
<appcomponent></appcomponent>
每个组件包括:
Dan 随后解释了每个部分的含义,以及它们如何融入 Angular 的组件开发方式。Angular 的一大优点在于其高度可预测性。一旦你学会了如何创建第一个组件,你就可以顺利地创建更多组件了。
第 7 部分:组件和模块 - 应用组件
在本课程的这一部分,我们将研究一个HelloWorld
组件。
Dan 为我们分解了组件的各个方面,并解释了如何使用它以及我们的组件如何被 Angular 处理,如何添加到app.module
我们的屏幕上以及最终如何在屏幕上呈现。
我们了解到,这selector: 'app-root'
允许我们稍后使用<app-root></app-root>
我们还对数据绑定进行了初步了解,我们将在后面的章节中详细了解它。
第 8 部分:组件和模块 - 应用模块
在这个截屏视频中,我们花了更多时间来了解app.module
我们在之前的视频中涉及的内部工作原理,并了解NgModule
和BrowserModule
。
第 9 部分:组件和模块 - 添加客户组件
在本期节目中,Dan 为我们提供了使用 CLI 创建组件的一些技巧,并演示了如何手动创建组件。我们将学习如何构建组件,并进一步扩展我们在第六部分中学到的知识。
现在我们引入一些数据来模拟我们的 API,并了解模块如何帮助我们保持代码的组织性并更易于重复使用。
第 10 部分:组件和模块 - 添加客户列表组件
在本部分中,我们创建一个customers-list.component
HTML 表格来显示客户列表。我们快速注册customers.module
并使用<app-customers-list></app-customers-list>
选择器显示空表格。
下一步是用一些数据填充表格。
第 11 部分:组件和模块 - 添加过滤文本框组件
在我们向表中添加一些数据之前,Dan 向我们展示了如何filter-textbox.component
向表中添加数据,并且我们强化了 Angular 创建组件、在模块中注册它以及在 HTML 中使用选择器的组件方式。
第 12 部分:组件和模块 — 添加共享模块和接口
在本节中,Dan 讨论了使用shared.module
- 一个模块,我们将想要在整个应用程序中共享的组件或其他功能放在其中,而不仅仅是在 中customers
。
我们还快速回顾了 TypeScript 接口以及如何在 Angular 应用程序中使用它们来提供更好的代码帮助并提高生产力。
export interface ICustomer {
id: number;
name: string;
city: string;
orderTotal?: number;
customerSince: any;
}
第 13 部分:数据绑定 - 数据绑定概述
在本章中,我们将学习数据绑定,学习一些技术并了解如何将数据绑定添加到我们的应用程序中。
我们通常在模板中绑定数据。当组件获取数据并将其挂接到模板中时,数据绑定就会发挥作用。我们可以使用 将数据导入模板Property Binding
,并使用 处理用户事件并从模板中获取数据Event Binding
。Angular 提供了一种强大而简洁的方法在模板中添加数据绑定,既快捷又易记。
Dan 为我们提供了一张方便的幻灯片来记住所需的语法……
...还有一些关于 Angular 指令的内容,例如ngFor
,用于循环遍历集合中的项目并从项目中获得一些属性,以及ngIf
从 DOM 中添加和删除 HTML 元素。
第 14 部分:数据绑定 - 数据绑定入门
在本例中,我们将利用上一章的知识来尝试Property Binding
并更好地理解它们在 Angular 中的工作方式。Event Binding
Dan 展示了如何使用该[hidden]
属性来动态显示h1
元素:
<h1 [hidden]="!isVisible">{{ title }}</h1>
并绑定 DOM 事件,例如单击:
<button (click)="changeVisibility()">Show/Hide</button>
第 15 部分:数据绑定 — 指令和插值
这里我们来看一下插值。其原理是,我们需要从每个客户那里获取数据,以便在第 10 部分中的表中生成一行。
这是一切开始融合的部分:我们使用指令ngFor
循环遍历每个客户,filteredCustomers
并将客户数据插入到表格行中。我们学习了一些使用 有条件渲染数据的技巧ngIf
。
最后我们得到了一张漂亮的桌子!
第十六部分:数据绑定 - 事件绑定
Event Binding
当我们需要处理事件(例如鼠标移动或点击)时,这一点至关重要。在这个截屏视频中,Dan 指导我们添加功能来对表中的数据进行排序。我们将从本章开始学习,并在课程的服务部分完成。
我们在中创建一个占位符事件处理程序customer-list.component
:
sort(prop: string) {
// A sorter service will handle the sorting
}
添加绑定customers-list.component.html
:
<tr>
<th (click)="sort('name')">Name</th>
<th (click)="sort('city')">City</th>
<th (click)="sort('orderTotal')">Order Total</th>
</tr>
第 17 部分:数据绑定 - 输入属性
people
我们的数组中有一些数据customers.component
,我们需要将其传递到我们的filteredCustomers
数组中customers-list.component
,从而有效地将数据从父组件传递到子组件。
为此,我们将使用Input
依赖于名为 Input() 的装饰器的 Angular 属性:
@Input() get customers(): ICustomer[] {
return this._customers
}
set customers(value: ICustomer[]) {
if (value) {
this.filteredCustomers = this._customers = value;
this.calculateOrders();
}
}
并在我们的父组件模板中绑定它以将数据从父组件传递到子组件(在本例中为 app-customers-list):
<app-customers-list [customers]="people"></app-customers-list>
第 18 部分:数据绑定 - 使用管道
哇!到目前为止我们做得还不错!
有些事情可能看起来有点奇怪——“john”是小写的,而且我们没有“$”符号来显示我们订单的货币。
这实际上是我们拥有数据的方式,因此我们可以直接去更新它,或者我们可以使用名为 Pipes 的内置 Angular 功能来为我们更新它!
一些最简单的管道看起来像这样:
{{ cust.name | uppercase }} // renders JOHN
{{ cust.name | titlecase }} // renders John
但有时您可能想要拥有自己的自定义管道,Dan 向我们展示了如何构建自定义capitalize
管道(请注意,Angular 包含一个名为titlecase
- 但我们在这里学习!)以及如何将其连接起来以在我们的应用程序中使用。
第 19 部分:数据绑定 - 添加过滤
filter-textbox.component
在这次演练中,Dan 带领我们了解如何从第 11 部分开始添加功能
Output
我们了解有关 Angular和属性的更多信息EventEmitter
,创建我们的过滤器事件处理程序并将其绑定到我们的过滤器文本框:
<filter-textbox (changed)="filter($event)"></filter-textbox>
好了,我们现在可以根据客户的姓名进行过滤!
第 20 部分:服务和 Http — 服务概述
在本章中,我们将探讨 Angular 服务。Angular 的一大优势在于它是一个完整的框架,内置了通过服务管理状态和对象的功能。我们在之前的图中见过服务。由于我们不希望组件知道太多功能,因此我们将依赖服务与服务器通信、执行客户端验证或计算等。
组件应该专注于呈现数据和处理用户事件。当需要执行其他功能时,应将其委托给服务,以提供更易于维护的应用程序和更好的代码复用。
这正是 Service 所做的——为应用程序提供一些可重复使用的功能,而这些功能不应该由任何组件来关注。
幸运的是,丹给我们准备了一张方便的幻灯片,让我们牢记在心。
第 21 部分:服务和 Http — 创建和提供服务
从前面的章节中,我们已经看到一个导入,Injectible
它是一个装饰器,允许实现所谓的依赖注入或简称 DI(Angular 内置的另一个强大功能)。
我们将使用 DI 来访问一个HttpClient
服务,该服务将用于与 RESTful 服务进行通信。我们将在构造函数中添加 HttpClient data.service
,并通过@Injectible()
装饰器来实现 DI。
第 22 部分:服务和 Http — 使用 HttpClient 调用服务器
在这次演讲中,Dan 介绍了 Observables RxJS
——JavaScript 的反应式扩展,它不是 Angular 的一部分,但默认包含在所有 Angular 项目中。
我们将使用 Observable 来处理异步代码。简而言之,它允许我们启动一个操作,然后订阅返回的数据。一旦数据从服务器返回,订阅就会结束,我们可以取消订阅。
Dan 讨论了调用服务器然后使用 RxJS 管道和运算符订阅响应所需的代码。
以下是我们如何获取订单的示例:
第 23 部分:服务和 Http — 将服务注入组件
现在我们有了获取数据的方法,我们需要将服务注入到我们的某个组件中。现在,我们可以从硬编码的方式改为this.people
调用customers.component
服务并以此方式获取数据。
我们需要把我们的带到data.service
,app.module
然后customers.component
我们就可以:
import { DataService } from '../core/data.service';
现在我们可以DataService
直接注入到组件的构造函数中:
constructor(private dataService: DataService) {}
第 24 部分:服务和 Http — 订阅可观察对象
现在我们可以使用我们的注入dataService
,调用getCustomers()
并订阅我们的Observable<ICustomer[]>
来获取数据。
这很简单:
ngOnInit() {
this.title = 'Customers';
this.dataService.getCustomers()
.subscribe((customers: ICustomer[]) =>
this.people = customers);
现在我们来看看最后一项服务—— SorterService
第 25 部分:服务和 Http — 使用 SorterService
目前,如果我们点击列标题,什么也不会发生。
Dan 很方便地为我们提供了一个预先写好的服务,我们可以使用它,所以在本章中,我们将练习将服务引入我们的组件中,在本例中是customers-list.component
。
与其他服务一样,我们需要导入它:
import { SorterService } from '../../core/sorter.service';
然后我们注入SorterService
到我们的构造函数中:
constructor(private sorterService: SorterService) {}
依赖注入使得访问可重用代码(例如排序器或数据服务)变得非常容易。
最后,我们在sort()
函数中使用它:
sort(prop: string) {
this.sorterService.sort(this.filteredCustomers, prop);
}
第 26 部分:路由 - 路由概述
本章将介绍路由,它是现代应用程序的重要组成部分。在构建 Angular 应用时,您需要在用户与其交互时显示不同的组件。在我们的例子中,当用户点击“客户”时,我们可能希望向他们显示“订单”。路由是一种非常巧妙地实现此目的的方法。
路由用于将特定的 URL 挂接到组件,在接下来的几章中,我们将重点关注 Angular 图的顶部。
路由的一个非常好的部分是,如果用户将特定的 URL 加入书签,它会将他们带回到特定的组件,而不需要复杂的显示/隐藏逻辑。
第 27 部分:路由 - 使用路由创建路由模块
我们从一个熟悉的模块容器例程开始并创建一个app-routing.module
。
主要重点app-routing.module
是在数组中定义路由:
const routes: Routes = [
{ path: '', pathMatch: 'full', redirectTo: '/customers'},
{ path: '**', redirectTo: '/customers' }
];
的三个关键属性routes
是:
path
— 用户访问的位置,也path: ''
就是应用的根目录。path: '**'
是一个通配符匹配。它通常放在最后,用于覆盖任何未在routes
pathMatch
— 路由应该如何精确匹配才能显示特定的组件redirectTo
— 当路径匹配时,我们会将用户发送到此处。在本例中,我们将用户发送到/customers
。
第 28 部分:路由 - 使用 Router Outlet
为了在app.component
模板中使用 Angular 中的路由,我们将 替换<app-customers></app-customers>
为<router-outlet></router-outlet>
。归根结底,这只是一种说法:“嘿,当我们到达路线时,组件将去往此处”。
当我们点击一条路线时,与该路线关联的组件就会神奇地出现在的位置<router-outlet></router-outlet>
。
第 29 部分:路由 - 添加客户路由模块和路由
在本章中,丹将所有事物整合在一起,我们将/customer
路线连接到customers.component
。
首先,我们创建一个customers-routing.module
并从第 28 部分指向的路线,customers.component
如下所示:
const routes: Routes = [
{ path: 'customers', component: CustomersComponent }
];
现在,当我们在 Scrimba 浏览器地址栏中输入“客户”时,我们会得到customers.component
.
第 30 部分:路由 - 添加带有路由的订单组件
在这个片段中,我们将快速回顾如何通过路由显示客户,现在是时候通过路由显示他们的订单了。
不过,还有一个小问题。当我们点击某个客户时,我们需要显示与该客户相关的订单数据。所以我们需要将一些动态数据传递到路由中。
我们可以通过像这样传递来实现这route parameter
一点orders-routing.module
:
const routes: Routes = [
{ path: 'orders/:id', component: OrdersComponent}
];
注意/:id
语法。在路由中, :
符号 表示其后的值将被动态替换,并且id
只是一个变量,因此它可以是任何值,例如 :country
或 :book
。
第 31 部分:路由 - 访问路由参数
在上一个截屏视频中,我们了解了如何创建orders/:id
路线,现在orders.component
需要以某种方式获取路线id
并显示与客户相关的订单。为此,我们需要访问id
路线参数。
一种方法是:
let id = this.route.paramMap.get('id');
这种方式的好处是,我们可以订阅paramMap
并在任何数据发生id
变化时收到通知。但我们只需要一次。
我们可以使用snapshot
:
let id = this.route.snapshot.paramMap.get('id')
snapshot
只需对您的 URL 进行即时拍照并提供给您,这非常完美,因为这正是我们在这种情况下所需要的。
但现在我们遇到了一个问题。我们的id
是一个字符串,但要从 中获取订单,DataService
它必须是数字。我们可以用 来转换它parseInt()
,但 Dan 教了我们一个巧妙的+
技巧:
let id = +this.route.snapshot.paramMap.get('id')
现在我们可以调用DataService
来获取订单并将其呈现给orders.component
。
第 32 部分:路由 - 使用 routerLink 指令链接到路由
我们要做的最后一件事是在客户姓名上添加一个链接,以便我们单击它来查看他们的订单。
在第 28 部分中,我们已经添加了<router-outlet></router-outlet
,现在我们只需要告诉我们的应用程序,我们希望orders.component
在导航到时显示/orders/:id
。
customers-list.component.html
我们可以在映射所有待显示数据的行中添加指向客户姓名的链接来实现。我们已经在那里保存了客户对象,因此可以直接将其传递id
给路由。
<a [routerLink]="['/orders', cust.id]">
{{ cust.name | capitalize }}
</a>
现在我们可以看到订单了!
可是,我们怎么返回呢?我们可以点击浏览器上的“返回”按钮,但既然我们知道了路由,最好有一个应用链接。我们把它添加到customers-list.component.html
最底部。
<a routerLink="/customers">View All Customers</a>
第 33 部分:课程总结
做得很好,我们现在有我们的应用程序了!
我们可以总结一下,快速回顾一下之前做过的事情。别忘了看看课程的实际截屏视频,Dan 是一位很棒的老师,跟着他一起学习整个过程一定会很有趣!
谢谢你,丹!
如果您有兴趣了解前端和后端技术,请务必在 Twitter 上关注 Dan!
文章来源:https://dev.to/scrimba/want-to-learn-angular-here-s-our-free-33-part-course-by-dan-wahlin-5880