Что нового в Angular 14?

Узнайте, что изменилось!

Введение

Angular 14 был недавно выпущен с кучей интересных функций. И сегодня я представлю их вам. Это:

  1. Автономные компоненты
  2. Провайдеры маршрутов
  3. ENVIRONMENT_INITIALIZER
  4. Типизированные формы
  5. Функция inject()
  6. Установка заголовка страницы из маршрута
  7. Автозаполнение в Angular CLI
  8. Дополнительные инжекторы во встроенных представлениях

Итак, давайте приступим!

Автономные компоненты

Для большинства людей самым значительным изменением в этой версии является возможность создания компонентов без @NgModules! Да, вы правильно поняли.

До Angular 14

Если вы немного заблудились, позвольте мне показать вам структуру папок классического компонента Angular:

home 
| --home.component.html
|--home.component.css
|--home.component.ts
|--home.module.ts;
Вход в полноэкранный режим Выход из полноэкранного режима

Здесь у нас есть файл .html для шаблона, файл .css для стилей, файл .ts для компонента и еще один файл .ts для @NgModule. Этот последний файл импортирует зависимости нашего компонента, объявляет компонент, а также может определять некоторые провайдеры.

Новая возможность в Angular 14

В Angular 14 мы можем делать все это непосредственно в компоненте, без использования @NgModule.

home 
|--home.component.html 
|--home.component.css 
|--home.component.ts;
Вход в полноэкранный режим Выйти из полноэкранного режима

Для этого нам просто нужно установить свойство standalone в нашем компоненте в true.

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.scss'],
  standalone: true,
})
Вход в полноэкранный режим Выход из полноэкранного режима

Будьте внимательны!

Будьте внимательны:

  1. Автономные компоненты — это не новый способ объявления компонентов! Это другой способ объявления компонентов. Классический способ определения @NgModules не будет устаревшим.

Ну, я не могу обещать, что он не будет устаревшим. Но да, пока что нет никаких намерений обесценивать @NgModules.

На самом деле. Я по-прежнему буду использовать @NgModules вместо отдельных компонентов, потому что мне нравится изоляция, которую обеспечивает @NgModules.

  1. Не переводите пока все приложение на автономные компоненты! Автономные компоненты появились совсем недавно, и нам потребуется некоторое время, чтобы создать соглашения и определить лучшие практики. Я рекомендую подождать еще немного, прежде чем переходить на новые компоненты.

Провайдеры маршрутов

Но если мы откажемся от @NgModule и будем использовать автономные компоненты, как мы сможем установить провайдера по маршруту, как мы это делали раньше с @NgModules?

Чтобы решить эту проблему, Angular добавил провайдеры маршрутов. Итак, в основном, определения маршрутов теперь имеют свойство providers. Это позволяет нам предоставлять значения только модулям и компонентам, отображаемым этим маршрутом.

const NAME = new InjectionToken<string>('token');

export const routes: Routes = [
  {
    path: '',
    component: HomeComponent,
    providers: [
      {
        provide: NAME,
        useValue: 'foo'
      }
    ]
  }
];
Вход в полноэкранный режим Выход из полноэкранного режима

ИНИЦИАЛИЗАТОР ОКРУЖЕНИЯ

Еще одна вещь, которую мы делали с NgModules — это запуск скрипта настройки при инициализации лениво загруженного модуля. Другими словами, конструктор лениво загруженного модуля запускался только при инициализации модуля, и некоторые разработчики пользовались этим, чтобы запустить какую-нибудь настройку.

export class HomeModule {
  constructor() {
    console.log('You can run something here');
  }
}
Вход в полноэкранный режим Выход из полноэкранного режима

Как мы можем сделать это с отдельными компонентами? Решением является использование маркера ENVIRONMENT_INITIALIZER.

const routes: Routes = [
  {
    path: '',
    pathMatch: 'full',
      component: HomeComponent
    providers:[
      {
        provide: ENVIRONMENT_INITIALIZER,
        multi: true,
        useValue: () => console.log("You can run something right here too")
      }
    ]
  }
]
Вход в полноэкранный режим Выход из полноэкранного режима

Этот маркер позволяет нам предоставить функцию настройки, которая будет выполняться до инициализации среды.

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

Это дает тот же эффект, что и предыдущее решение с использованием NgModule constructors, но имеет дополнительное преимущество — более явный характер.

Типизированные формы

Еще одна долгожданная функция Angular 14 — типизированные формы.

До версии 14 значения форм типизировались как any. Это означает, что мы теряем всю потрясающую безопасность типов TypeScript.

  const control = new FormControl(""),
    control.value
    //=> control.value: any
Вход в полноэкранный режим Выход из полноэкранного режима

Кстати, существует безопасный для типов способ сказать, что вы не знаете тип чего-либо. Если вам это интересно, посмотрите это одноминутное видео, объясняющее разницу между any и unknown.

В любом случае, у нас больше нет такой проблемы. Потому что Angular 14 имеет строгие типы для форм. Так что если FormControl имеет дело с string, значение будет набрано как string вместо any.

const control = new FormControl(""),
control.value
//=> control.value: string | null
Вход в полноэкранный режим Выход из полноэкранного режима

Функция inject()

Это самая интересная функция для меня.

Angular 14 вводит функцию inject(). И она очень похожа на React hooks. Она дает нам целую вселенную возможностей для повторного использования нашего кода, наиболее актуальной из которых является то, что теперь мы можем создавать многократно используемые функции, которые используют инъекцию зависимостей внутри.

export function getPosts() {
  const http = inject(HttpClient);
  return http.get('/api/getPosts');
}

export class HomeComponent {
  readonly posts = getPosts();
}
Вход в полноэкранный режим Выход из полноэкранного режима

Если вы, как и я, интересуетесь функциональным программированием, вы знаете, что это много значит! Но, как однажды сказал дядя Бен:

«С большой силой приходит большая ответственность».

Это создает неявные зависимости в ваших функциях. Я ожидаю, что зависимости в функциях будут явно объявлены в аргументах функции. Поэтому, если я вижу функцию без аргументов, я считаю, что у нее нет зависимостей. Но теперь мы можем создавать функции, которые кажутся чистыми, но при этом содержат множество внутренних зависимостей, что делает их более сложными для тестирования и более привязанными к фреймворку Angular.

Хорошим решением будет следовать тому же соглашению, что и в React, а именно: добавлять к функциям префикс "use". Таким образом, вы сможете легко определить функции, которые используют inject() внутри.

export function useGetPosts() {
  const http = inject(HttpClient);
  return http.get('/api/getPosts');
}

export class HomeComponent {
  readonly posts = useGetPosts();
}
Вход в полноэкранный режим Выход из полноэкранного режима

Установка заголовка страницы из маршрута

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

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

export const routes: Routes = [
  {
    path: '',
    component: HomeComponent,
    title: 'Home',
    pathMatch: 'full'
  }
];
Вход в полноэкранный режим Выход из полноэкранного режима

Но я знаю, о чем вы думаете:

«Лукас, я не могу задать заголовок в определении маршрута, потому что мой заголовок не статичен, он зависит от того, что я получаю из API».

Не волнуйтесь. Angular 14 позаботился о вас.

Если вам нужно настроить заголовок динамически, вы можете сделать это, расширив класс TitleStrategy из @angular/router и предоставив свою новую, пользовательскую стратегию заголовка вместо стратегии по умолчанию.

@Injectable({ providedIn: 'root' })
export class PageTitleStrategy extends TitleStrategy {
  constructor(@Inject(Title) private title: Title) {
    super();
  }

  override updateTitle(routerState: RouterStateSnapshot) {
    const title = this.buildTitle(routerState);
    if (title !== undefined) {
      this.title.setTitle(`CompanyName | ${title}`);
    } else {
      this.title.setTitle(`CompanyName | Page without title`);
    }
  }
}

export const routes: Routes = [
  {
    path: '',
    component: HomeComponent,
    title: 'Home',
    pathMatch: 'full'
  }
];

bootstrapApplication(AppComponent, {
  providers: [
    importProvidersFrom(RouterModule.forRoot(routes)),
    { provide: TitleStrategy, useClass: PageTitleStrategy }
  ]
});
Вход в полноэкранный режим Выход из полноэкранного режима

Автозаполнение в Angular CLI

Еще одна приятная мелочь — автозаполнение в Angular CLI.

Просто введите ng в терминале и нажмите TAB, чтобы Angular CLI либо автозаполнил вашу команду, либо выдал вам подсказку.

> ng se
            //=> If you press TAB here, the CLI will complete

> ng serve
Вход в полноэкранный режим Выход из полноэкранного режима
> ng
        //=> If you press TAB here, the CLI will show a list of commands

> ng
    add           -- Adds support for an external library to your project.
    analytics     -- Configures the gathering of Angular CLI usage metrics.
    build         -- Compiles an Angular application or library into an outpu...
    cache         -- Configure persistent disk cache and retrieve cache sta...
    ...
Войти в полноэкранный режим Выход из полноэкранного режима

Активация автозаполнения CLI

Чтобы активировать его, необходимо выполнить команду ng completion и подтвердить, что вы хотите включить автозаполнение, набрав Yes.

> ng completion

? Would you like to enable autocompletion? This will set up your terminal so pressing
TAB while typing Angular CLI commands will show possible options and autocomplete arguments.
(Enabling autocompletion will modify configuration files in your home directory.)

> Yes
Вход в полноэкранный режим Выход из полноэкранного режима

Наконец, просто перезапустите терминал, чтобы автозаполнение было включено.

Дополнительные инжекторы во встроенных представлениях

И последнее, но не менее важное: теперь мы можем передавать необязательные инжекторы во встроенных представлениях. Раньше для этого приходилось использовать другие API, например, ngComponentOutlet.

@Directive({ selector: '[foo]' })
export class FooDirective implements OnInit {
  constructor(
    private vcr: ViewContainerRef,
    private templateRef: TemplateRef<unknown>
  ) {}

  ngOnInit(): void {
    this.vcr.createEmbeddedView(
      this.templateRef,
      {}, // context
      {
        injector: Injector.create({
          // pass an injector :)
          providers: [
            {
              provide: 'foo',
              useValue: 'bar'
            }
          ]
        })
      }
    );
  }
}
Вход в полноэкранный режим Выход из полноэкранного режима

Не останавливайтесь на достигнутом

Это были самые важные изменения в Angular 14, на мой взгляд. Если вы хотите ознакомиться со всеми изменениями, вы можете сделать это, посмотрев ссылки в описании.

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

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

Как всегда, ссылки в описании. Нравится. Подписывайтесь. Хорошего дня. И до встречи в следующем.

— Лукас

Ссылки

  1. Angular 14 — Academind на Youtube
  2. O que há de novo no revolucionário Angular 14 — Andrew Rosário on Medium
  3. Нововведения в Angular v14 — Vida Fullstack
  4. Что нового в Angular 14? — Nevzatopcu на Medium
  5. Angular v14 уже доступен! — Блог Angular на Medium
  6. Что нового в Angular v14 — Нетанель Басал
  7. Раскройте мощь DI-функций в Angular — Нетанель Басал
  8. Знакомство с маркером инъекции ENVIRONMENT_INITIALIZER в Angular — Netanel Basal
  9. Типизированные реактивные формы в Angular — больше не мечта о типах — Нетанель Басал
  10. Обработка заголовков страниц в Angular — Netanel Basal
  11. Автономные компоненты Angular: Добро пожаловать в мир без NgModule — Netanel Basal
  12. Передача инжектора встроенным представлениям — Netanel Basal
  13. Установка заголовка страницы из модуля route — Брендон Робертс
  14. Автономные компоненты с пользовательской стратегией заголовка в Angular 14

Оцените статью
devanswers.ru
Добавить комментарий