Статьи

Создайте свое первое угловое приложение: хранение и доступ к данным

В первом уроке из этой серии мы узнали, как начать работу над созданием приложения Angular . После успешного завершения этого урока у вас должно появиться первое работающее приложение Angular с заголовком «Интересные факты о странах». Прежде чем создавать какие-либо компоненты, которые можно отобразить на экране, мы создадим несколько классов и определим некоторые функции, которые делают эти компоненты полезными.

В этом уроке мы сосредоточимся на создании класса Country который будет содержать различные свойства, значение которых мы хотим отобразить пользователю. Затем мы создадим еще один файл с именем country-data.ts . Этот файл будет содержать информацию обо всех странах в нашем приложении. Наш третий файл будет называться country.service.ts . Название может показаться причудливым, но файл будет содержать класс CountryService со всеми необходимыми функциями для извлечения и сортировки информации, предоставленной файлом country-data.ts .

В папке src/app вашего приложения Angular создайте файл с именем country.ts . Добавьте следующий код внутри него.

1
2
3
4
5
6
7
8
export class Country {
    name: string;
    capital: string;
    area: number;
    population: number;
    currency: string;
    gdp: number;
}

Приведенный выше код TypeScript определяет класс Country с шестью различными свойствами для хранения информации о разных странах. Название страны, ее столица и валюта хранятся в виде строки. Тем не менее, его площадь, население и ВВП хранятся в виде числа. Мы будем импортировать класс Country во многих местах, поэтому я добавил ключевое слово export перед определением класса.

Следующий шаг включает в себя создание файла country-data.ts для хранения информации обо всех странах в виде массива объектов Country . Мы будем импортировать класс Country в этом файле, а затем экспортировать const именем COUNTRIES который хранит массив объектов страны.

Вот код для country-data.ts . Точно так же, как country.ts , вы должны создать этот файл в папке src/app .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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: ‘China’,
    capital: ‘Beijing’,
    area: 9596961,
    population: 1403500365,
    currency: ‘Renminbi (Yuan)’,
    gdp: 11199145
  },
  {
    name: ‘United States’,
    capital: ‘Washington, DC’,
    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 выдаст вам следующую ошибку:

1
Cannot find name ‘Country’.

Без оператора import TypeScript не будет иметь представления о том, что означает массив типа Country . Поэтому убедитесь, что вы импортировали правильный класс и правильно указали местоположение country.ts .

После импорта класса Country мы продолжаем создавать массив объектов Country . Мы будем импортировать этот массив стран для использования в других файлах, поэтому мы также добавим ключевое слово export в этот массив. В настоящее время в массиве есть пять различных объектов Country . Каждый из этих пяти объектов предоставляет пары ключ-значение, в которых перечислены имя свойства и его значение для определенного объекта или страны.

Если вы попытаетесь добавить в массив дополнительное свойство, которое не было объявлено в определении класса Country , вы получите следующую ошибку:

1
Object literal may only specify known properties, and ‘president’ does not exist in type ‘Country’

В этом случае я пытался сохранить имя президента в виде string внутри свойства с именем president . Так как никакое такое свойство не было объявлено, мы получили ошибку. Иногда вам может потребоваться указать свойство только для определенных объектов, а не для других. В таких случаях вы можете пометить свойство как необязательное внутри определения класса. Я обсудил это более подробно в руководстве, которое охватывает интерфейсы TypeScript .

Пока просто убедитесь, что имена всех свойств совпадают с именами внутри определения класса. Также убедитесь, что значение каждого свойства имеет тот же тип, который объявлен в определении класса.

После создания нашего класса Country и массива COUNTRIES теперь мы можем наконец написать некоторые функции для обработки данных о стране. Нам потребуется импортировать как класс Country и массив COUNTRIES внутри нашего сервисного файла. Файл должен будет импортировать массив COUNTRIES , чтобы иметь доступ к данным. Точно так же файл должен будет импортировать класс Country , чтобы иметь смысл данных в массиве COUNTRIES .

Мы также будем импортировать другие зависимости, такие как Injectable from Angular core, чтобы сделать наш класс CountryService доступным для Inject для внедрения в другие компоненты.

Как только ваше приложение увеличится в размере, различные модули должны будут общаться друг с другом. Допустим, что ModuleA требует ModuleB для правильной работы. В таких случаях мы будем называть ModuleB зависимостью от ModuleA .

Простой импорт нужного нам модуля в другой файл работает большую часть времени. Однако иногда нам нужно решить, следует ли нам создавать один экземпляр классов из ModuleB который будет использоваться всем приложением, или нам следует создавать новый экземпляр каждый раз, когда используется модуль. В нашем случае мы будем внедрять один экземпляр нашего класса CountryService в приложение.

Вот код для country.service.ts :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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() принимает массив getPopulatedCountries() и сортирует его в порядке убывания в зависимости от населения разных стран. Затем мы используем метод Array.slice () , чтобы вернуть первые три страны (с индексами 0, 1 и 2) из ​​массива. getLargestCountries() и getGDPCountries() работают аналогичным образом.

Метод getCountry() принимает имя в качестве аргумента и возвращает объект страны, свойство name которого имеет то же значение, что и предоставленный аргумент name.

Созданный вами сервис — это просто класс в Angular, пока вы не зарегистрируете его с помощью инжектора зависимостей Angular. Угловой инжектор будет ответственным за создание экземпляра (ов) службы и внедрение их в различные классы, которые нуждаются в этой услуге. Нам нужно зарегистрировать сервис у провайдера, прежде чем инжектор сможет создать этот сервис.

Существует два распространенных способа регистрации любой службы: с помощью поставщика @Component или с @NgModule поставщика @NgModule . Использование поставщика @Component имеет смысл, когда вы хотите ограничить доступ службы к определенному компоненту и всем его вложенным компонентам. Использование поставщика @NgModule имеет смысл, если вы хотите, чтобы несколько компонентов имели доступ к службе.

В нашем случае мы будем использовать CountryService с несколькими компонентами нашего приложения. Это означает, что мы должны зарегистрировать его у поставщика @NgModule один раз, а не регистрировать отдельно у поставщика @Component каждого компонента.

В настоящее время ваш файл app.module.ts должен выглядеть следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
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 поставщиков @NgModule . После внесения этих изменений ваш файл app.module.ts должен выглядеть следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
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-data.ts используется для хранения массива объектов страны, которые имеют информацию о разных странах. Файл country.service.ts содержит класс обслуживания с различными методами для доступа к данным страны из массива COUNTRIES . Написание всех этих методов отдельно внутри класса обслуживания позволяет нам получить доступ к ним внутри различных компонентов приложения из центрального расположения

В последнем разделе мы зарегистрировали наш сервис у провайдера @NgModule , чтобы сделать его доступным для использования внутри различных компонентов.

В следующем уроке вы узнаете, как создать три различных компонента в вашем приложении для отображения сведений о стране и списка стран.