От автора: Angular обладает множеством функций, как популярных, так и неизвестных. Самый простой способ найти оптимальные приемы для решения сложных задач с помощью Angular — это еще больше использовать Angular и учиться в процессе. Вот мои любимые примеры того, как можно использовать Angular, и советы по работе с ним.
Angular — это JavaScript-фреймворк для создания веб-приложений, в часности одностраничных. В качестве основы, он предлагает лучшие практики и инструменты для простой разработки этих веб-приложений. При сборке с помощью Angular вы будете использовать декларативные шаблоны, включение зависимостей и т. д. для поддержки приложений, которые могут работать на всех платформах (веб, мобильных и настольных).
Angular предоставляет свои лучшие практики для упрощения разработки с использованием фреймворка, но могут быть и другие упущенные советы, которые, скорее всего, облегчат разработку или помогут вашему приложению работать и загружаться быстрее. Итак, вот семь советов и приемов, чтобы сделать приложения Angular лучше.
1. Используйте службы для обработки побочных эффектов
При создании приложения всегда полезно уменьшить побочные эффекты, такие как HTTP-запросы, события, основанные на тайминге, и т. д. Абстрагирование их из компонента в службы поможет снизить сложность компонента, а также обеспечит возможность повторного использования службы. Примером может служить получение данных с внешнего сервера. Вы можете получить данные внутри компонента следующим образом:
import { Component } from "@angular/core"; @Component({ selector: 'app-component', template: '<ul> <li *ngFor="let item of items">{{item}}</li> </ul>', }) export class AppComponent implements OnInit{ constructor(private http: HttpClient){ } items = []; getItems(){ return this.http.get('http://server.com/items') } ngOnInit(){ this.getItems.subscribe(items => this.items = items); } }
Этот метод, используемый при извлечении элементов, является локальным для компонента и не может использоваться повторно, и если элементы выбираются в других компонентах, вся эта процедура будет повторена, и это не очень DRY. Если выполнено несколько сетевых запросов, компонент будет загроможден этими методами. Давайте проведем рефакторинг этого компонента, чтобы использовать службу для внешних запросов.
@Injectable({ providedIn: 'root' }) export class ItemService { constructor (private http: HttpClient) {} getItems() { return this.http.get('http://server.com/items'); } }
После этого мы используем ее в компоненте:
import { Component } from "@angular/core"; @Component({ selector: 'app-component', template: '<ul> <li *ngFor="let item of items">{{item}}</li> </ul>', }) export class AppComponent implements OnInit{ constructor(private itemsService: ItemsService){ } items = []; ngOnInit(){ this.itemsServices.getItems().subscribe(items => this.items = items); } }
Эта служба может быть использована для извлечения элементов во всем приложении.
2. ng add
Эта утилита, представленная в Angular версии 6, может быть использована для добавления опубликованного пакета в вашу рабочую среду, и она будет запускать схемы в фоновом режиме для обновления функционала приложения. При загрузке пакета с помощью этой команды она также устанавливает дополнительные зависимости, которые ему необходимо запустить, например, полифиллы и т. д. Приложение может быть преобразовано в прогрессивное веб-приложение с использованием service worker и предоставлением автономных функций с помощью команды.
Вы можете реализовать в своем приложении прогрессивные функции веб-приложения, выполнив следующую команду:
ng add @angular/pwa
Или, если вы хотите добавить в приложение Material Design, вы можете добавить библиотеку Angular Material.
ng add @angular/material
3. Веб-компоненты
Начиная с версии Angular 6, вы можете создавать собственные нативные элементы, которые можно использовать за пределами Angular. Это можно сделать с помощью пакета Angular, называемого Angular Elements (@angular/elements). Этот пакет предоставляет способ выполнить createCustomElements и полифилы для поддержки браузеров, которые не совместимы с веб-компонентами. С помощью этого пакета вы можете упаковать свои любимые компоненты и использовать их в других средах, таких как React, Vue и т. д.
Чтобы начать создавать в Angular собственные нативные элементы, установите пакет Angular Elements в своем приложении с помощью следующей команды:
ng add @angular/elements --name=<your_project_name>
Вы можете следовать краткому руководству из официальной документации Angular.
4. Псевдонимы для операторов импорта
Эта очень полезная функция поддерживается в Angular. Я уверен, что вы сталкивались со случаями, когда импорт в ваших приложениях просто грязный и трудный для чтения. У нас есть что-то вроде:
import { ThatComponent } from '../../../components/this-component/child-component' import { ThisService } from '../../../../services/this-service'
Я уверен, что будет более полезно задать псевдонимы для путей components и services — это сделало бы эти импорты относительно легко читаемыми.
Работая с React, я исследовал, как этого добиться, но большинство решений включают в себя удаление вашего приложения, что не очень приятно. Что ж, для достижения этого в приложении Angular все, что вам нужно сделать, это обновить файл tsconfig.json:
{ "compileOnSave": false, "compilerOptions": { "baseUrl": "src", "paths": { "@components": "app/components", "@services": "app/services", }, "..." } }
Здесь значение свойства baseUrl по умолчанию ./ было обновлено, чтобы указывать на каталог src. Затем мы добавили новое свойство с именем paths, представляющее собой объект, содержащий пары ключей-значений, предоставляющих псевдонимы, определенные для путей в приложении. Псевдонимы были определены для папки components и папки services. Теперь, если мы хотим выполнить импорт в предыдущем примере, мы сделаем это:
import { ThatComponent } from '@components/this-component/child-component'; import { ThisService } from '@services/this-service';
Это намного чище и проще для чтения, чем в предыдущем примере. Если вы еще не загрузили свой редактор, чтобы сделать это в приложении, то советую вам не медлить.
5. Оператор безопасного перехода для интерполяции строк
При работе с объектами в шаблонах Angular вы сталкиваетесь с ситуациями, когда переменные объявляются без значений по умолчанию — переменная просто представляется как определение типа. При попытке получить доступ к свойству переменной, которая недоступна, Angular выдаст ошибку, сообщив, что переменная не определена. Например, ваш шаблон выглядит так: вы читаете свойство name объекта student:
<p>{{ student.name }}</p>
А вот как переменная была объявлена в файле компонента:
interface Student { name: String; age: Number: } @Component({ selector: 'app-component', }) export class AppComponent{ student: Student; }
Angular выдаст ошибку. Используя оператор безопасного перехода, мы можем обеспечить, что для свойства name не будет задано nullи undefined. Оператор безопасного перехода в Angular — это синтаксис ?., и мы можем обновить шаблон, чтобы использовать его:
<p> {{ student?.name }} </p>
Когда вы запустите этот код, Angular не выдаст ошибок, и консоль будет чиста. Другой полезный способ избежать этой ошибки — использование оператора and (&&) для проверки существования значения перед чтением пути свойства. Мы можем обновить пример, чтобы использовать этот синтаксис:
<p> {{ student && student.name }} </p>
Если значение не существует, Angular избегает вычисления выражения, и между тегами ничего не отображается.
6. Корректно обрабатывайте ошибки с помощью обработчика ошибок
Angular поставляется со службой обработки исключений, которую можно использовать для управления ошибками в масштабах всего приложения. Когда служба обнаруживает ошибки, она перехватывает их и записывает в консоль. Этот сервис может быть расширен для добавления дополнительных функций, уникальных для нашего приложения, таких как регистрация ошибок с помощью платформы мониторинга ошибок или отправка ошибок на сервер для аналитики.
Обработчик ошибок довольно легко расширить: нам нужно создать объект class, который расширяет свойства ErrorHandler и переопределяет встроенный метод handleError, используемый для отображения ошибок. Создайте файл с именем error-handler.class.ts:
import {ErrorHandler} from '@angular/core'; // Вымышленная библиотека мониторинга ошибок import ErrorClient from '@error-reporters/core'; // Инициализируем библиотеку отчетов const reporter = new ErrorClient(); export class AppErrorHandler extends ErrorHandler { constructor(private errorService: ErrorService){ super(false); } public handleError(error: any): void { reporter.sendReport(error) super.handleError(error); } }
В приведенном выше фрагменте кода мы использовали вымышленную библиотеку отчетов и мониторинга ошибок, которая называется @error-reporters. После расширения службы ErrorHandler мы сообщим об ошибках, исходящих из приложения в методе handleError, прежде чем обрабатывать ошибку методом ErrorHandler — handleError.
После этого нам нужно зарегистрировать пользовательский AppErrorHandler в app.module.ts:
@NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule ], bootstrap: [ AppComponent ], providers: [ {provide: ErrorHandler, useClass: AppErrorHandler} ] })
7. Отложенная загрузка нежизненноважных компонентов
При работе с довольно большими приложениями или при запуске одного из них будет полезно обеспечить отложенную загрузку компонентов, не необходимых для первоначальной визуализации вашего приложения. Отложенная загрузка означает, что они загружаются по требованию. Например, когда пользователь отклоняется от начального представления приложения, выполняется сетевой запрос на загрузку целевого маршрута. Отложенная загрузка может эффективно уменьшить размер пакета приложения, тем самым сокращая время загрузки приложения в браузере.
Отложенная загрузка компонентов начинается с создания функционального модуля в приложении, в функциональном модуле будут размещены компоненты, службы, провайдеры и т. д., к которым он прикреплен. Затем функциональный модуль загружается в корневой модуль маршрутизации приложения. Посмотрите на пример ниже:
import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FeatureRoutingModule } from './feature-routing.module'; import { FeatureComponent } from './feature/feature.component'; @NgModule({ imports: [ CommonModule, FeatureRoutingModule ], declarations: [FeatureComponent] }) export class FeatureModule { }
Этот функциональный модуль FeatureModule содержит один компонент FeatureComponent и подключенный к нему модуль маршрутизации FeatureRoutingModule.
Чтобы отложено загрузить этот компонент, мы зарегистрируем модуль маршрутизации функционального модуля в корневом модуле приложения:
import { NgModule } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { BrowserModule } from '@angular/platform-browser'; import { RouterModule } from '@angular/router'; import { AppComponent } from './app.component'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, FormsModule, RouterModule.forRoot([ { path: 'feature', loadChildren: './feature/feature.module#FeatureModule' } ]) ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
На этом этапе будет создан пакет отдельно от основного пакета приложения. Этот пакет будет загружаться, когда пользователь перейдет к маршруту /feature. Опыт может быть немного неприятным, потому что пользователю нужно будет ждать загрузки пакета маршрута, и это может занять некоторое время в зависимости от размера пакета.
Чтобы решить эту проблему, мы предварительно выберем другие пакеты в фоновом режиме после полной загрузки начальной страницы. Мы можем сделать это, используя встроенный флаг Angular, который называется preloadStrategy. Это указывает Angular, какую стратегию использовать при загрузке отложенных пакетов.
Давайте обновим текущую реализацию, чтобы использовать стратегию PreloadAllModules:
import { NgModule } from '@angular/core'; ... import { RouterModule, PreloadAllModules } from '@angular/router'; import { AppComponent } from './app.component'; @NgModule({ declarations: [ ... ], imports: [ ... RouterModule.forRoot([ { path: 'feature', loadChildren: './feature/feature.module#FeatureModule' } ], {preloadStrategy: PreloadAllModules}) ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
С этим обновлением Angular будет обрабатывать предварительную выборку комплектов объектов в фоновом режиме для удобной навигации.
Заключение
Angular — это фреймворк, что означает, что у него есть свой способ действовать и приносить результаты. Он обладает множеством функций, как популярных, так и неизвестных. Самый простой способ найти оптимальные приемы для решения сложных задач с помощью Angular — это еще больше использовать Angular и учиться в процессе. Перечисленные выше советы и приемы не полностью охватывают то, что можно сделать, используя расширенные возможности Angular.
Автор: Christian Nwamba
Источник: https://www.telerik.com
Редакция: Команда webformyself.