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

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

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

Содержание:

  • Введение в Angular
  • Настройка окружения для разработки
  • Основы Angular: компоненты, модули и сервисы
  • Routing в Angular
  • Создание многостраничного приложения
  • Работа с формами
  • HTTP-запросы и взаимодействие с API
  • Аутентификация и авторизация
  • Оптимизация производительности
  • Тестирование Angular-приложений
  • Развертывание приложения

Введение в Angular

Angular — это платформа и фреймворк для создания клиентских приложений на HTML и TypeScript. Он реализует основные и дополнительные функции как набор библиотек TypeScript, которые импортируются в приложения.

Ключевые особенности Angular:

  • Компонентная архитектура
  • Шаблоны на основе HTML
  • Зависимость от инъекций
  • Модульность
  • Встроенный роутинг
  • Поддержка TypeScript

Angular предоставляет разработчикам мощный инструментарий для создания сложных веб-приложений. Его архитектура позволяет легко масштабировать проекты и поддерживать их на протяжении длительного времени.

Настройка окружения для разработки

Перед началом работы с Angular необходимо настроить окружение для разработки. Это включает в себя установку Node.js, npm (Node Package Manager) и Angular CLI (Command Line Interface).

Шаги по настройке окружения:

  1. Установить Node.js и npm с официального сайта nodejs.org
  2. Открыть терминал и выполнить команду: npm install -g @angular/cli
  3. Проверить установку, выполнив команду: ng version

После успешной установки Angular CLI, можно приступать к созданию нового проекта.

Создание нового проекта Angular:

Для создания нового проекта необходимо выполнить следующую команду в терминале:

ng new my-angular-app

Angular CLI задаст несколько вопросов о конфигурации проекта, после чего создаст базовую структуру приложения.

Основы Angular: компоненты, модули и сервисы

Angular основан на концепции компонентов, модулей и сервисов. Понимание этих базовых элементов необходимо для эффективной разработки приложений.

Компоненты

Компоненты являются основными строительными блоками пользовательского интерфейса в Angular-приложениях. Каждый компонент состоит из:

  • HTML-шаблона, определяющего представление
  • Класса TypeScript, управляющего данными и логикой
  • CSS-стилей, определяющих внешний вид

Пример простого компонента:

 import { Component } from '@angular/core'; @Component({ selector: 'app-hello', template: '

{{ greeting }}

', styles: ['h1 { color: blue; }'] }) export class HelloComponent { greeting = 'Hello, Angular!'; }

Модули

Модули в Angular используются для организации приложения и его функциональности. Они группируют связанные компоненты, директивы, сервисы и другие файлы. Каждое Angular-приложение имеет как минимум один корневой модуль, обычно называемый AppModule.

Пример модуля:

 import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { AppComponent } from './app.component'; @NgModule({ imports: [BrowserModule], declarations: [AppComponent], bootstrap: [AppComponent] }) export class AppModule { } 

Сервисы

Сервисы в Angular используются для организации и совместного использования бизнес-логики, моделей данных, функций для работы с сетью и других операций, не связанных напрямую с представлением. Они внедряются в компоненты с помощью механизма внедрения зависимостей.

Пример сервиса:

 import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class DataService { getData() { return ['Item 1', 'Item 2', 'Item 3']; } } 

Routing в Angular

Routing является ключевым элементом в создании многостраничных приложений на Angular. Он позволяет определять различные пути (URL) и связывать их с компонентами, создавая навигацию по приложению.

Читайте также  Повышение читаемости кода React

Настройка маршрутизации

Для настройки маршрутизации в Angular необходимо выполнить следующие шаги:

  1. Импортировать RouterModule в главный модуль приложения
  2. Определить маршруты
  3. Добавить <router-outlet> в шаблон
  4. Создать навигацию

Пример конфигурации маршрутов:

 import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { HomeComponent } from './home/home.component'; import { AboutComponent } from './about/about.component'; const routes: Routes = [ { path: '', component: HomeComponent }, { path: 'about', component: AboutComponent } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { } 

Навигация в приложении

Для создания навигации в Angular-приложении используется директива routerLink. Она позволяет создавать ссылки на различные маршруты.

Пример навигационного меню:

 <nav> <ul> <li><a routerLink="/">Home</a></li> <li><a routerLink="/about">About</a></li> </ul> </nav> <router-outlet></router-outlet> 

Создание многостраничного приложения

Теперь, когда рассмотрены основные концепции Angular и настройка маршрутизации, можно приступить к созданию многостраничного приложения.

Структура проекта

Типичная структура многостраничного Angular-приложения может выглядеть следующим образом:

 src/ app/ home/ home.component.ts home.component.html home.component.css about/ about.component.ts about.component.html about.component.css contact/ contact.component.ts contact.component.html contact.component.css shared/ header/ header.component.ts header.component.html header.component.css footer/ footer.component.ts footer.component.html footer.component.css app.component.ts app.component.html app.component.css app.module.ts app-routing.module.ts index.html styles.css main.ts 

Создание компонентов

Для каждой страницы приложения создается отдельный компонент. Это можно сделать с помощью Angular CLI:

 ng generate component home ng generate component about ng generate component contact 

Каждая команда создаст новый компонент с соответствующими файлами (.ts, .html, .css).

Настройка маршрутизации

В файле app-routing.module.ts необходимо определить маршруты для каждого компонента:

 import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { HomeComponent } from './home/home.component'; import { AboutComponent } from './about/about.component'; import { ContactComponent } from './contact/contact.component'; const routes: Routes = [ { path: '', component: HomeComponent }, { path: 'about', component: AboutComponent }, { path: 'contact', component: ContactComponent }, { path: '**', redirectTo: '' } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { } 

Создание навигации

В главном компоненте приложения (app.component.html) создается навигационное меню:

 <header> <nav> <ul> <li><a routerLink="/">Home</a></li> <li><a routerLink="/about">About</a></li> <li><a routerLink="/contact">Contact</a></li> </ul> </nav> </header> <main> <router-outlet></router-outlet> </main> <footer> <p>&copy; 2024 My Angular App</p> </footer> 

Работа с формами

Формы являются важной частью многих веб-приложений. Angular предоставляет два подхода к работе с формами: реактивные формы и формы на основе шаблонов.

Реактивные формы

Реактивные формы предоставляют модельно-ориентированный подход к обработке входных данных формы. Они более масштабируемы и подходят для сложных сценариев.

Пример реактивной формы:

 import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; @Component({ selector: 'app-contact', template: ` <form [formGroup]="contactForm" (ngSubmit)="onSubmit()"> <input formControlName="name" placeholder="Name"> <input formControlName="email" placeholder="Email"> <textarea formControlName="message" placeholder="Message"></textarea> <button type="submit" [disabled]="!contactForm.valid">Send</button> </form> ` }) export class ContactComponent implements OnInit { contactForm: FormGroup; constructor(private fb: FormBuilder) {} ngOnInit() { this.contactForm = this.fb.group({ name: ['', Validators.required], email: ['', [Validators.required, Validators.email]], message: ['', Validators.required] }); } onSubmit() { if (this.contactForm.valid) { console.log(this.contactForm.value); } } } 

Формы на основе шаблонов

Формы на основе шаблонов используют директивы для создания и манипулирования формой. Они проще в использовании и подходят для небольших форм.

Пример формы на основе шаблона:

 import { Component } from '@angular/core'; @Component({ selector: 'app-login', template: ` <form (ngSubmit)="onSubmit()"> <input [(ngModel)]="username" name="username" placeholder="Username" required> <input [(ngModel)]="password" name="password" type="password" placeholder="Password" required> <button type="submit">Login</button> </form>
`
})
export class LoginComponent {
username: string;
password: string;

onSubmit() {
console.log('Username:', this.username);
console.log('Password:', this.password);
}
}

HTTP-запросы и взаимодействие с API

Для взаимодействия с серверным API Angular предоставляет HttpClient модуль. Он позволяет выполнять HTTP-запросы и обрабатывать ответы.

Читайте также  Обзор лучших интегрированных баз данных для JS-приложений

Настройка HttpClient

Сначала необходимо импортировать HttpClientModule в главный модуль приложения:

 import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { HttpClientModule } from '@angular/common/http'; import { AppComponent } from './app.component'; @NgModule({ imports: [BrowserModule, HttpClientModule], declarations: [AppComponent], bootstrap: [AppComponent] }) export class AppModule { } 

Создание сервиса для работы с API

Рекомендуется создавать отдельные сервисы для работы с API. Вот пример сервиса для работы с API пользователей:

 import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class UserService { private apiUrl = 'https://api.example.com/users'; constructor(private http: HttpClient) { } getUsers(): Observable<any> { return this.http.get(this.apiUrl); } getUser(id: number): Observable<any> { return this.http.get(`${this.apiUrl}/${id}`); } createUser(user: any): Observable<any> { return this.http.post(this.apiUrl, user); } updateUser(id: number, user: any): Observable<any> { return this.http.put(`${this.apiUrl}/${id}`, user); } deleteUser(id: number): Observable<any> { return this.http.delete(`${this.apiUrl}/${id}`); } } 

Использование сервиса в компоненте

Теперь можно использовать созданный сервис в компонентах для выполнения HTTP-запросов:

 import { Component, OnInit } from '@angular/core'; import { UserService } from './user.service'; @Component({ selector: 'app-user-list', template: ` <ul> <li *ngFor="let user of users">{{ user.name }}</li> </ul> ` }) export class UserListComponent implements OnInit { users: any[]; constructor(private userService: UserService) { } ngOnInit() { this.userService.getUsers().subscribe( (data) => { this.users = data; }, (error) => { console.error('Error fetching users:', error); } ); } } 

Аутентификация и авторизация

Реализация аутентификации и авторизации является важной частью многих веб-приложений. В Angular это можно реализовать с помощью сервисов и гвардов (guards).

Сервис аутентификации

Создадим сервис для управления аутентификацией:

 import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { BehaviorSubject, Observable } from 'rxjs'; import { map } from 'rxjs/operators'; @Injectable({ providedIn: 'root' }) export class AuthService { private currentUserSubject: BehaviorSubject<any>; public currentUser: Observable<any>; constructor(private http: HttpClient) { this.currentUserSubject = new BehaviorSubject<any>(JSON.parse(localStorage.getItem('currentUser'))); this.currentUser = this.currentUserSubject.asObservable(); } public get currentUserValue() { return this.currentUserSubject.value; } login(username: string, password: string) { return this.http.post<any>('https://api.example.com/login', { username, password }) .pipe(map(user => { localStorage.setItem('currentUser', JSON.stringify(user)); this.currentUserSubject.next(user); return user; })); } logout() { localStorage.removeItem('currentUser'); this.currentUserSubject.next(null); } } 

Гвард для защиты маршрутов

Создадим гвард для защиты маршрутов, требующих аутентификации:

 import { Injectable } from '@angular/core'; import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; import { AuthService } from './auth.service'; @Injectable({ providedIn: 'root' }) export class AuthGuard implements CanActivate { constructor( private router: Router, private authService: AuthService ) { } canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { const currentUser = this.authService.currentUserValue; if (currentUser) { return true; } this.router.navigate(['/login'], { queryParams: { returnUrl: state.url } }); return false; } } 

Применение гварда к маршрутам

Теперь можно применить гвард к защищенным маршрутам в конфигурации маршрутизации:

 import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { HomeComponent } from './home/home.component'; import { LoginComponent } from './login/login.component'; import { ProfileComponent } from './profile/profile.component'; import { AuthGuard } from './auth.guard'; const routes: Routes = [ { path: '', component: HomeComponent }, { path: 'login', component: LoginComponent }, { path: 'profile', component: ProfileComponent, canActivate: [AuthGuard] } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { } 

Оптимизация производительности

Оптимизация производительности является важным аспектом разработки Angular-приложений. Рассмотрим несколько техник для улучшения производительности.

Ленивая загрузка модулей

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

Читайте также  Рекомендации по созданию эффективных React-компонентов

Пример настройки ленивой загрузки:

 const routes: Routes = [ { path: '', component: HomeComponent }, { path: 'admin', loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule) } ]; 

Использование OnPush стратегии обнаружения изменений

Стратегия OnPush позволяет оптимизировать процесс обнаружения изменений в компонентах:

 import { Component, ChangeDetectionStrategy } from '@angular/core'; @Component({ selector: 'app-my-component', template: '...', changeDetection: ChangeDetectionStrategy.OnPush }) export class MyComponent { } 

Использование trackBy в ngFor

Использование trackBy в директиве ngFor может значительно улучшить производительность при работе с большими списками:

 <li *ngFor="let item of items; trackBy: trackByFn">{{ item.name }}</li> trackByFn(index, item) { return item.id; } 

Оптимизация рендеринга

Для оптимизации рендеринга можно использовать такие техники, как:

  • Виртуальная прокрутка для больших списков
  • Использование pure pipes вместо методов в шаблонах
  • Минимизация вложенности компонентов

Тестирование Angular-приложений

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

Модульное тестирование

Для модульного тестирования в Angular используется Jasmine в сочетании с Karma. Вот пример теста для сервиса:

 import { TestBed } from '@angular/core/testing'; import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; import { UserService } from './user.service'; describe('UserService', () => { let service: UserService; let httpMock: HttpTestingController; beforeEach(() => { TestBed.configureTestingModule({ imports: [HttpClientTestingModule], providers: [UserService] }); service = TestBed.inject(UserService); httpMock = TestBed.inject(HttpTestingController); }); afterEach(() => { httpMock.verify(); }); it('should retrieve users', () => { const dummyUsers = [ { id: 1, name: 'John' }, { id: 2, name: 'Jane' } ]; service.getUsers().subscribe(users => { expect(users.length).toBe(2); expect(users).toEqual(dummyUsers); }); const req = httpMock.expectOne('https://api.example.com/users'); expect(req.request.method).toBe('GET'); req.flush(dummyUsers); }); }); 

Тестирование компонентов

Для тестирования компонентов можно использовать TestBed и создавать фиктивные (mock) зависимости:

 import { ComponentFixture, TestBed } from '@angular/core/testing'; import { UserListComponent } from './user-list.component'; import { UserService } from './user.service'; import { of } from 'rxjs'; describe('UserListComponent', () => { let component: UserListComponent; let fixture: ComponentFixture<UserListComponent>; let userServiceSpy: jasmine.SpyObj<UserService>; beforeEach(async () => { const spy = jasmine.createSpyObj('UserService', ['getUsers']); await TestBed.configureTestingModule({ declarations: [ UserListComponent ], providers: [ { provide: UserService, useValue: spy } ] }).compileComponents(); userServiceSpy = TestBed.inject(UserService) as jasmine.SpyObj<UserService>; }); beforeEach(() => { fixture = TestBed.createComponent(UserListComponent); component = fixture.componentInstance; }); it('should create', () => { expect(component).toBeTruthy(); }); it('should load users', () => { const users = [{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }]; userServiceSpy.getUsers.and.returnValue(of(users)); fixture.detectChanges(); expect(component.users).toEqual(users); }); }); 

Развертывание приложения

После разработки и тестирования приложения следующим шагом является его развертывание. Angular CLI предоставляет инструменты для сборки приложения для производственного использования.

Сборка приложения

Для сборки приложения используется следующая команда:

ng build --prod

Эта команда создаст оптимизированную версию приложения в директории dist/.

Оптимизация сборки

Для дальнейшей оптимизации сборки можно использовать следующие техники:

  • Включение Ahead-of-Time (AOT) компиляции
  • Минификация и обфускация кода
  • Оптимизация изображений
  • Использование сжатия gzip

Развертывание на сервере

После сборки приложения его можно развернуть на веб-сервере. Для этого необходимо:

  1. Скопировать содержимое директории dist/ на сервер
  2. Настроить сервер для обработки маршрутов Angular

Пример конфигурации для Nginx:

 server { listen 80; server_name example.com; root /path/to/dist/folder; index index.html; location / { try_files $uri $uri/ /index.html; } } 

Заключение

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

Советы по созданию сайтов