在本系列的第一个教程中,我们学习了如何开始创建 angular 应用程序。成功完成该教程后,您现在应该拥有您的第一个功能正常的 Angular 应用程序,其标题为“关于***的有趣事实”。在创建可以在屏幕上呈现的任何组件之前,我们将创建一些类并定义一些使这些组件有用的函数。
在本教程中,我们的重点将是创建一个Country
类,该类将包含我们希望向用户显示其值的不同属性。然后,我们将创建另一个名为country-data.ts
. 此文件将包含有关我们应用程序中所有***/地区的信息。我们的第三个文件将命名为country.service.ts
. 这个名字可能听起来很花哨,但该文件将只包含一个CountryService
类,该类具有检索和排序文件提供的信息所需的所有功能country-data.ts
。
创建***类
在src/app
Angular 应用的文件夹中,创建一个名为country.ts
. 在其中添加以下代码。
export class Country { name: string; capital: string; area: number; population: number; currency: string; gdp: number; }
上面的 typescript 代码定义了 Country
具有六个不同属性的类来存储有关不同***的信息。***名称、首都和货币以字符串形式存储。但是,它的面积、人口和 GDP 以数字形式存储。我们将Country
在很多地方导入类,所以我export
在类定义之前添加了关键字。
创建一系列***
下一步包括创建一个文件,将所有***/地区的信息存储为对象country-data.ts
数组。Country
我们将Country
在这个文件中导入类,然后导出一个存储***对象数组的 const
命名。COUNTRIES
这是country-data.ts
. 就像country.ts
,您必须在文件夹中创建此文件src/app
。
import { Country } from './country'; export const COUNTRIES: Country[] = [ { name: 'Russia', capital: 'Moscow', area: 17098246, population: 144463451, currency: 'Russian Ruble', gdp: 1283162 }, { name: 'Canada', capital: 'Ottawa', area: 9984670, population: 35151728, currency: 'Canadian Dollar', gdp: 159760 }, { name: '***', capital: 'Beijing', area: 9596961, population: 1403500365, currency: 'Renminbi (Yuan)', gdp: 11199145 }, { name: 'United States', capital: 'Washington, D.C.', area: 9525067, population: 325365189, currency: 'United States Dollar', gdp: 18569100 }, { name: 'Japan', capital: 'Tokyo', area: 377972, population: 12676200, currency: 'Yen', gdp: 4939384 } ];
此文件中的第一行从位于同一目录中的文件中导入Country
类。country.ts
如果你从文件中删除这一行,TypeScript 会给你以下错误:
Cannot find name 'Country'.
如果没有 import 语句,TypeScript 将不知道类型数组的Country
含义。因此,请确保您已导入正确的类并country.ts
正确指定了位置。
导入Country
类后,我们继续创建一个Country
对象数组。我们将导入这个***数组以在其他文件中使用,所以我们也export
向这个数组添加一个关键字。目前,数组中有五个不同Country
的对象。这五个对象中的每一个都提供键值对,其中列出了属性名称及其特定对象或***/地区的值。
如果您尝试向尚未在Country
类定义中声明的数组添加其他属性,您将收到以下错误:
Object literal may only specify known properties, and 'president' does not exist in type 'Country'
在这种情况下,我试图将总统的名字存储为一个string
名为president
. 由于没有声明这样的属性,我们得到了一个错误。有时,您可能只想为特定对象而不是其他对象指定属性。在这种情况下,您可以在类定义中将属性标记为可选。我在涵盖 TypeScript Interfaces的教程中更详细地讨论了它。
现在,只需确保所有属性的名称与类定义中的名称匹配。还要确保每个属性的值与类定义中声明的类型相同。
创建 CountryService 类
在创建了我们的Country
类和COUNTRIES
数组之后,我们现在终于可以编写一些函数来处理***数据了。我们需要在我们的服务文件中导入Country
类和COUNTRIES
数组。该文件需要导入COUNTRIES
数组才能访问数据。同样,该文件必须导入Country
该类才能理解COUNTRIES
数组中的数据。
我们还将Injectable
从 Angular 核心导入其他依赖项,以使我们的CountryService
类可用于 Injector 以注入其他组件。
一旦你的应用程序变大,不同的模块将需要相互通信。假设 ModuleA
需要ModuleB
才能正常工作。在这种情况下,我们将ModuleB
调用ModuleA
.
大多数情况下,只需将我们需要的模块导入另一个文件即可。然而,有时我们需要决定是否应该创建一个ModuleB
将被整个应用程序使用的类的单个实例,或者我们是否应该在每次使用模块时创建一个新实例。在我们的例子中,我们将在CountryService
整个应用程序中注入我们类的单个实例。
这是代码country.service.ts
:
import { Injectable } from '@angular/core'; import { Country } from './country'; import { COUNTRIES } from './country-data'; @Injectable() export class CountryService { constructor() { } getCountries(): Country[] { return COUNTRIES; } getPopulatedCountries(): Country[] { return COUNTRIES.sort((a, b) => b.population - a.population).slice(0, 3); } getLargestCountries(): Country[] { return COUNTRIES.sort((a, b) => b.area - a.area).slice(0, 3); } getGDPCountries(): Country[] { return COUNTRIES.sort((a, b) => b.gdp - a.gdp).slice(0, 3); } getCountry(name: string): Country { return COUNTRIES.find(country => country.name === name); } }
装饰器@injectable
用于标识可能需要注入依赖项的服务类。但是,添加@injectable
到服务类是一种必需的编码风格,所以我们还是这样做了。
之后,我们为类编写不同的方法,这些方法获取COUNTRIES
数组并直接返回它,或者使用某些标准对其进行排序,然后返回数组的一部分。
该getCountries()
方法应返回所有 Country
对象,因此它返回整个COUNTRIES
数组而不对其进行任何修改。
getPopulatedCountries()
获取数组并根据 COUNTRIES
不同***的人口按降序对其进行排序。然后我们使用Array.slice()方法从数组中返回前三个***(索引为 0、1 和 2)。getLargestCountries()
和getGDPCountries()
方法以类似的方式工作。
该getCountry()
方法将名称作为其参数并返回其名称属性与提供的名称参数具有相同值的***/地区对象。
在 app.module.ts 中包含 CountryService
您创建的服务只是 Angular 中的一个类,直到您使用 Angular 依赖注入器注册它。Angular 注入器将负责创建服务实例并将它们注入到需要该服务的不同类中。我们需要先向提供者注册服务,然后注入器才能创建该服务。
注册任何服务有两种常用方法:使用 @Component
提供者或使用@NgModule
提供者。当您想要限制服务对特定组件及其所有嵌套组件的访问时,使用@Component
提供程序是有意义的。当您希望多个组件访问服务时,使用提供程序是有意义的。@NgModule
在我们的例子中,我们将使用CountryService
我们应用程序的多个组件。这意味着我们应该向@NgModule
提供者注册一次,而不是分别向@Component
每个组件的提供者注册。
目前,您的app.module.ts
文件应如下所示:
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
将导入语句添加到app.module.ts
文件并将服务添加到@NgModule
提供程序数组。进行这些更改后,您的app.module.ts
文件应如下所示:
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; import { CountryService } from './country.service'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule ], providers: [CountryService], bootstrap: [AppComponent] }) export class AppModule { }
现在CountryService
,我们为应用程序创建的所有组件都可以使用该类。
最后的想法
成功创建名为country.ts
、 、 的三个文件country-data.ts
,并country.service.ts
结束本系列的第二篇教程。
该country.ts
文件用于创建Country
具有不同属性的类,如名称、货币、人口、面积等。该country-data.ts
文件用于存储具有不同***信息的***对象数组。该文件包含一个服务类,该服务类具有从数组country.service.ts
中访问***数据的不同方法 。COUNTRIES
在服务类中单独编写所有这些方法允许我们从一个中心位置在不同的应用程序组件中访问它们。