Пошаговое создание первого приложения на Angular

Пошаговое создание первого приложения на Angular

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

Содержание:

  • Подготовка окружения
  • Создание нового проекта
  • Структура проекта Angular
  • Компоненты в Angular
  • Шаблоны и стили
  • Работа с данными и сервисы
  • Маршрутизация
  • Формы и валидация
  • HTTP-запросы и взаимодействие с API
  • Оптимизация производительности
  • Тестирование приложения
  • Сборка и деплой

Подготовка окружения

Перед началом работы над проектом необходимо убедиться, что на компьютере установлены все необходимые инструменты. Для разработки на Angular потребуются:

  • Node.js (версия 12.x или выше)
  • npm (Node Package Manager)
  • Angular CLI (Command Line Interface)

Для установки Node.js нужно перейти на официальный сайт и скачать установщик для соответствующей операционной системы. После установки Node.js, npm будет автоматически установлен вместе с ним.

Следующим шагом является установка Angular CLI. Для этого нужно открыть терминал и выполнить следующую команду:

npm install -g @angular/cli

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

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

Для создания нового проекта Angular используется команда ng new. Откройте терминал, перейдите в директорию, где будет располагаться проект, и выполните следующую команду:

ng new my-first-angular-app

Angular CLI задаст несколько вопросов о конфигурации проекта:

  • Would you like to add Angular routing? (Y/n) — Добавить ли маршрутизацию?
  • Which stylesheet format would you like to use? — Какой формат стилей использовать?

Для первого проекта можно выбрать «Yes» для маршрутизации и CSS в качестве формата стилей.

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

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

После создания проекта, можно изучить его структуру. Основные файлы и директории:

  • src/ — исходный код приложения
  • src/app/ — компоненты, сервисы и модули приложения
  • src/assets/ — статические файлы (изображения, шрифты и т.д.)
  • src/environments/ — конфигурации для разных окружений (разработка, продакшн)
  • src/index.html — главный HTML-файл приложения
  • src/main.ts — точка входа в приложение
  • src/styles.css — глобальные стили
  • angular.json — конфигурация Angular CLI
  • package.json — зависимости и скрипты npm
  • tsconfig.json — конфигурация TypeScript

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

ng serve

После выполнения этой команды, приложение будет доступно по адресу http://localhost:4200/.

Компоненты в Angular

Компоненты — это основные строительные блоки Angular-приложений. Каждый компонент состоит из трех основных частей:

  • Шаблон (HTML)
  • Стили (CSS)
  • Класс компонента (TypeScript)

Давайте создадим новый компонент с помощью Angular CLI:

ng generate component hello-world

Эта команда создаст новый компонент HelloWorldComponent и добавит его в модуль приложения. Теперь отредактируем файл src/app/hello-world/hello-world.component.ts:

import { Component } from '@angular/core'; @Component({ selector: 'app-hello-world', templateUrl: './hello-world.component.html', styleUrls: ['./hello-world.component.css'] }) export class HelloWorldComponent { message: string = 'Привет, Angular!'; } 

Затем обновим шаблон компонента в файле src/app/hello-world/hello-world.component.html:

<h1>{{ message }}</h1>

Теперь можно использовать этот компонент в главном компоненте приложения. Отредактируем файл src/app/app.component.html:

<h1>Мое первое Angular-приложение</h1> <app-hello-world></app-hello-world>

Шаблоны и стили

Angular использует расширенный синтаксис HTML для создания динамических шаблонов. Вот некоторые основные концепции:

  • Интерполяция: {{ выражение }}
  • Привязка свойств: [свойство]=»выражение»
  • Привязка событий: (событие)=»обработчик()»
  • Двусторонняя привязка: [(ngModel)]=»свойство»
Читайте также  Второй видеоролик о проведении аудита сайтов от SEOs&DEVs

Давайте обновим наш компонент HelloWorld, добавив некоторые из этих концепций:

import { Component } from '@angular/core'; @Component({ selector: 'app-hello-world', templateUrl: './hello-world.component.html', styleUrls: ['./hello-world.component.css'] }) export class HelloWorldComponent { message: string = 'Привет, Angular!'; buttonText: string = 'Нажми меня'; clickCount: number = 0; onButtonClick() { this.clickCount++; this.message = `Кнопка была нажата ${this.clickCount} раз`; } } 

Обновим шаблон компонента:

<h1>{{ message }}</h1> <button [disabled]="clickCount > 10" (click)="onButtonClick()">{{ buttonText }}</button> <p>Количество кликов: {{ clickCount }}</p>

Для стилизации компонента можно использовать файл hello-world.component.css. Например:

h1 { color: #3f51b5; } button { background-color: #3f51b5; color: white; border: none; padding: 10px 20px; cursor: pointer; } button:disabled { background-color: #ccc; cursor: not-allowed; } p { font-style: italic; }

Работа с данными и сервисы

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

ng generate service data

Отредактируем файл src/app/data.service.ts:

import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class DataService { private data: string[] = ['Элемент 1', 'Элемент 2', 'Элемент 3']; getData(): string[] { return this.data; } addData(item: string): void { this.data.push(item); } } 

Теперь обновим наш компонент HelloWorld, чтобы использовать этот сервис:

import { Component } from '@angular/core'; import { DataService } from '../data.service'; @Component({ selector: 'app-hello-world', templateUrl: './hello-world.component.html', styleUrls: ['./hello-world.component.css'] }) export class HelloWorldComponent { items: string[] = []; newItem: string = ''; constructor(private dataService: DataService) { this.items = this.dataService.getData(); } addItem() { if (this.newItem.trim() !== '') { this.dataService.addData(this.newItem); this.items = this.dataService.getData(); this.newItem = ''; } } } 

Обновим шаблон компонента:

<h2>Список элементов</h2> <ul> <li *ngFor="let item of items">{{ item }}</li> </ul> <input [(ngModel)]="newItem" placeholder="Новый элемент"> <button (click)="addItem()">Добавить</button>

Не забудьте импортировать FormsModule в файле app.module.ts для использования [(ngModel)]:

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

Маршрутизация

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

ng generate component about

Теперь отредактируем файл src/app/app-routing.module.ts:

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

Обновим главный компонент приложения в файле src/app/app.component.html:

<nav> <ul> <li><a routerLink="/">Главная</a></li> <li><a routerLink="/about">О нас</a></li> </ul> </nav> <router-outlet></router-outlet>

Формы и валидация

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

ng generate component registration-form

Отредактируем файл src/app/registration-form/registration-form.component.ts:

import { Component } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; @Component({ selector: 'app-registration-form', templateUrl: './registration-form.component.html', styleUrls: ['./registration-form.component.css']
})
export class RegistrationFormComponent {
registrationForm: FormGroup;

constructor(private formBuilder: FormBuilder) {
this.registrationForm = this.formBuilder.group({
username: ['', [Validators.required, Validators.minLength(3)]],
email: ['', [Validators.required, Validators.email]],
password: ['', [Validators.required, Validators.minLength(6)]],
confirmPassword: ['', Validators.required]
}, { validator: this.passwordMatchValidator });
}

passwordMatchValidator(form: FormGroup) {
const password = form.get('password');
const confirmPassword = form.get('confirmPassword');
if (password && confirmPassword && password.value !== confirmPassword.value) {
confirmPassword.setErrors({ passwordMismatch: true });
} else {
confirmPassword?.setErrors(null);
}
}

onSubmit() {
if (this.registrationForm.valid) {
console.log('Форма отправлена', this.registrationForm.value);
} else {
console.log('Форма содержит ошибки');
}
}
}

Теперь создадим шаблон формы в файле src/app/registration-form/registration-form.component.html:

<form [formGroup]="registrationForm" (ngSubmit)="onSubmit()"> <div> <label for="username">Имя пользователя:</label> <input id="username" type="text" formControlName="username"> <div *ngIf="registrationForm.get('username')?.invalid && registrationForm.get('username')?.touched"> <p *ngIf="registrationForm.get('username')?.errors?.['required']">Имя пользователя обязательно</p> <p *ngIf="registrationForm.get('username')?.errors?.['minlength']">Минимальная длина имени - 3 символа</p> </div> </div> <div> <label for="email">Email:</label> <input id="email" type="email" formControlName="email"> <div *ngIf="registrationForm.get('email')?.invalid && registrationForm.get('email')?.touched"> <p *ngIf="registrationForm.get('email')?.errors?.['required']">Email обязателен</p> <p *ngIf="registrationForm.get('email')?.errors?.['email']">Некорректный формат email</p> </div> </div> <div> <label for="password">Пароль:</label> <input id="password" type="password" formControlName="password"> <div *ngIf="registrationForm.get('password')?.invalid && registrationForm.get('password')?.touched"> <p *ngIf="registrationForm.get('password')?.errors?.['required']">Пароль обязателен</p> <p *ngIf="registrationForm.get('password')?.errors?.['minlength']">Минимальная длина пароля - 6 символов</p> </div> </div> <div> <label for="confirmPassword">Подтверждение пароля:</label> <input id="confirmPassword" type="password" formControlName="confirmPassword"> <div *ngIf="registrationForm.get('confirmPassword')?.invalid && registrationForm.get('confirmPassword')?.touched"> <p *ngIf="registrationForm.get('confirmPassword')?.errors?.['required']">Подтверждение пароля обязательно</p> <p *ngIf="registrationForm.get('confirmPassword')?.errors?.['passwordMismatch']">Пароли не совпадают</p> </div> </div> <button type="submit" [disabled]="registrationForm.invalid">Зарегистрироваться</button> </form> 

Не забудьте импортировать ReactiveFormsModule в файле app.module.ts:

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

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

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

ng generate service api

Отредактируем файл src/app/api.service.ts:

import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class ApiService { private apiUrl = 'https://jsonplaceholder.typicode.com/posts'; constructor(private http: HttpClient) { } getPosts(): Observable { return this.http.get(this.apiUrl); } createPost(post: any): Observable { return this.http.post(this.apiUrl, post); } } 

Теперь создадим компонент для отображения постов:

ng generate component posts

Отредактируем файл src/app/posts/posts.component.ts:

import { Component, OnInit } from '@angular/core'; import { ApiService } from '../api.service'; @Component({ selector: 'app-posts', templateUrl: './posts.component.html', styleUrls: ['./posts.component.css'] }) export class PostsComponent implements OnInit { posts: any[] = []; newPost = { title: '', body: '' }; constructor(private apiService: ApiService) { } ngOnInit() { this.loadPosts(); } loadPosts() { this.apiService.getPosts().subscribe( (data) => { this.posts = data; }, (error) => { console.error('Ошибка при загрузке постов', error); } ); } createPost() { this.apiService.createPost(this.newPost).subscribe( (response) => { console.log('Пост создан', response); this.posts.unshift(response); this.newPost = { title: '', body: '' }; }, (error) => { console.error('Ошибка при создании поста', error); } ); } } 

Создадим шаблон для компонента в файле src/app/posts/posts.component.html:

<h2>Посты</h2> <form (ngSubmit)="createPost()"> <input [(ngModel)]="newPost.title" name="title" placeholder="Заголовок"> <textarea [(ngModel)]="newPost.body" name="body" placeholder="Текст поста"></textarea> <button type="submit">Создать пост</button> </form> <ul> <li *ngFor="let post of posts"> <h3>{{ post.title }}</h3> <p>{{ post.body }}</p> </li> </ul> 

Не забудьте импортировать HttpClientModule в файле app.module.ts:

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

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

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

  1. Ленивая загрузка модулей: Разделите приложение на модули и загружайте их по мере необходимости. Это уменьшит начальный размер бандла и ускорит загрузку приложения.
  2. Использование OnPush стратегии обнаружения изменений: Это поможет уменьшить количество проверок изменений в компонентах.
  3. Виртуальная прокрутка: Для больших списков используйте виртуальную прокрутку, чтобы отображать только видимые элементы.
  4. Кэширование: Используйте сервисы для кэширования данных, чтобы уменьшить количество запросов к серверу.
  5. Оптимизация изображений: Используйте оптимизированные изображения и ленивую загрузку для них.

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

import { Component, ChangeDetectionStrategy, Input } from '@angular/core'; @Component({ selector: 'app-optimized-component', template: ` <h2>{{ title }}</h2> <p>{{ content }}</p> `, changeDetection: ChangeDetectionStrategy.OnPush }) export class OptimizedComponent { @Input() title: string = ''; @Input() content: string = ''; } 

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

Тестирование приложения

Тестирование является важной частью разработки Angular-приложений. Angular предоставляет инструменты для модульного тестирования (unit testing) и интеграционного тестирования (integration testing). Давайте рассмотрим пример написания модульного теста для компонента:

import { ComponentFixture, TestBed } from '@angular/core/testing'; import { HelloWorldComponent } from './hello-world.component'; describe('HelloWorldComponent', () => { let component: HelloWorldComponent; let fixture: ComponentFixture; beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [ HelloWorldComponent ] }) .compileComponents(); }); beforeEach(() => { fixture = TestBed.createComponent(HelloWorldComponent); component = fixture.componentInstance; fixture.detectChanges(); }); it('should create', () => { expect(component).toBeTruthy(); }); it('should have a message', () => { expect(component.message).toBe('Привет, Angular!'); }); it('should increment clickCount on button click', () => { component.onButtonClick(); expect(component.clickCount).toBe(1); }); }); 

Для запуска тестов используется команда:

ng test

Эта команда запустит Karma — тестовый раннер, который выполнит все тесты в проекте и отобразит результаты.

Сборка и деплой

Когда приложение готово к выпуску, его нужно собрать для продакшена. Angular CLI предоставляет команду для создания оптимизированной сборки:

ng build --prod

Эта команда создаст оптимизированную версию приложения в директории dist/. Файлы в этой директории можно затем развернуть на веб-сервере.

Для простого деплоя можно использовать такие сервисы, как Firebase Hosting или GitHub Pages. Например, для деплоя на GitHub Pages можно использовать следующие шаги:

  1. Установите пакет angular-cli-ghpages:
    npm install -g angular-cli-ghpages
  2. Соберите приложение с правильным базовым URL:
    ng build --prod --base-href "https://<username>.github.io/<repository-name>/"
  3. Разверните приложение на GitHub Pages:
    ngh --dir=dist/<project-name>

После этих шагов приложение будет доступно по URL https://<username>.github.io/<repository-name>/.

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