Использование веб-компонентов в Angular

Использование веб-компонентов в Angular

От автора: Angular – фреймворк, любимый многими в сообществе JS. Angular предоставляет библиотеку для создания инкапсулированных компонентов, вставку зависимостей, создание языковых шаблонов с назначением данных, роутер приложения, построенный на observables, а также интерфейс командной строки с низким порогом входа. Этот фреймворк не такой гибкий, как другие, однако упрямый характер Angular позволяет большим командам кодить по существующим стандартам, а не разрабатывать свои. Также Angular упрощает разделение логики отображения (компоненты) от бизнес логики (сервисы и логика), поэтому несколько команд может работать над разными частям приложения.

Веб-компоненты

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

Angular

Angular 2+ делает много тяжелой работы за вас, компилируя шаблон компонента в рендерер JS и синхронизируя данные между ним и объектом компонента. Делается это через однонаправленный поток данных и менеджер жизненных циклов, который определяет изменения в свойствах компонента и указывает, какой шаблон необходимо заново отрендерить. Язык шаблонов Angular – это в основном HTML с синтаксическим сахаром, поэтому компилятор уже знает, как создавать узлы DOM по тегам в шаблоне. По умолчанию компилятор понимает только стандартные теги HTML и компоненты Angular, зарегистрированные в приложении. Как только компилятор Angular узнает о веб-компонентах, в приложении сразу можно использовать любой веб-компонент, зарегистрированный в браузере, как родной HTML элемент.

Начнем с генерации проекта с помощью angular-cli (полный код) и будем использовать те же веб-компоненты, что и в уроке по веб-компонентам в React. Начнем.

Активация веб-компонентов

Во-первых, давайте активируем веб-компоненты в нашем проекте в src/app/app.module.ts:

Практический курс по созданию веб-приложения на Angular4

Станьте профессиональным веб-разработчиком, создавая востребованные веб-приложения на Angular4.

Узнать подробнее
import { BrowserModule } from '@angular/platform-browser';
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
 
import { AppComponent } from './app.component';
 
import '../web-components/Tabs';
import '../web-components/Tab';
 
@NgModule({
  declarations: [
 AppComponent
  ],
  imports: [
 BrowserModule
  ],
  providers: [],
  bootstrap: [AppComponent],
  schemas: [
 CUSTOM_ELEMENTS_SCHEMA
  ]
})
export class AppModule { }

Сначала мы импортировали CUSTOM_ELEMENTS_SCHEMA из @angular/core и добавили ее в объявление @NgModule приложения в свойстве schemas. Так мы разрешаем компилятору шаблонов Angular веб-компоненты и их атрибуты. Также мы импортировали наши веб-компоненты, и они зарегистрировались браузером. Так как веб-компоненты – это JS файлы, то нам нужно сказать TypeScript, чтобы тот разрешил импорт JS файлов в tsconfig.json:

{
  "compileOnSave": false,
  "compilerOptions": {
 "outDir": "./dist/out-tsc",
 "sourceMap": true,
 "declaration": false,
 "moduleResolution": "node",
 "emitDecoratorMetadata": true,
 "experimentalDecorators": true,
 "target": "es5",
 "allowJs": true,
 "typeRoots": [
 "node_modules/@types"
 ],
 "lib": [
 "es2017",
 "dom"
 ]
  }
}

Мы добавили свойство compilerOptions.allowJs и установили ему значение true. Теперь мы можем использовать веб-компоненты в приложении Angular и компонентах.

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

Теперь когда компилятор Angular знает, что нужно разрешить наши кастомные теги, мы можем использовать веб-компоненты в любом шаблоне проекта. Начнем с добавления очень простого компонента статичных вкладок в src/app/app.component.html:

<x-tabs>
  <x-tab title="Tab 01" closable="true">
 <div>
 <h3>Tab 01 Content</h3>
 </div>
  </x-tab>
  <x-tab title="Tab 02">
 <div>
 <h3>Tab 02 Content</h3>
 </div>
  </x-tab>
</x-tabs>

Этот простой компонент вкладок использует первую версию рекомендаций веб-компонентов. Компонент x-tabs создаст маркированный список с заголовками x-tab, которые будут отвечать за каждую вкладку. Как видите, в разметке не сказано, где и как ul будет отрисован, что делает его хорошим компонентом, так как часть компонента генерируется динамически. В компоненте есть события, которые будут запущены, динамически генерируя разметку внутри компонента и модифицируя структуру DOM.

Обработка событий и коллекций

Когда закрывается вкладка, которую можно закрыть, компонент x-tabs запускает событие tabclosed. Обработка событий веб-компонентов следует тому же подходу, который используется в событиях компонентов Angular. Мы изменим наш шаблон (src/app/app.component.html), чтобы прикрепить событие:

<x-tabs (tabclosed)="onTabClosed($event)">
  <x-tab title="Tab 01" closable="true">
 <div>
 <h3>Tab 01 Content</h3>
 </div>
  </x-tab>
  <x-tab title="Tab 02">
 <div>
 <h3>Tab 02 Content</h3>
 </div>
  </x-tab>
</x-tabs>

И добавим метод onTabClosed в наш компонент (src/app/app.component.ts):

onTabClosed({ detail: component }) {
  console.log(component);
}

При запуске приложения клик по кнопке закрытия первой вкладки запускает наш обработчик события и логирует узел x-tab, который был удален.

Так как Angular видит веб-компоненты как компоненты первого уровня, мы можем с помощью декоратора @ViewChildren собрать вкладки с шаблона. Нам нужно изменить шаблон и добавить в узлы x-tab идентификаторы:

Практический курс по созданию веб-приложения на Angular4

Станьте профессиональным веб-разработчиком, создавая востребованные веб-приложения на Angular4.

Узнать подробнее
<x-tabs (tabclosed)="onTabClosed($event)">
  <x-tab title="Tab 01" #tab closable="true">
 <div>
 <h3>Tab 01 Content</h3>
 </div>
  </x-tab>
  <x-tab #tab title="Tab 02">
 <div>
 <h3>Tab 02 Content</h3>
 </div>
  </x-tab>
</x-tabs>

Добавим свойство с декоратором @ViewChildren в наш компонент:

@ViewChildren('tab') tabs: QueryList<ElementRef>;

Теперь если открыть приложение в Augury, то можно заметить, что свойство tabs наполнено объектами ElementRef, в которых хранятся ссылки на компоненты x-tab:

Использование веб-компонентов в Angular

Встает одна проблема: при закрытии первой вкладки не обновляется коллекция tabs. Так происходит потому, что шаблон приложения не обновляется, когда изменяется нижележащий DOM (как наш компонент x-tabs). Если запустить повторный рендеринг компонента, это откроет закрытую вкладку.

Управление вкладками

В простом приложении без закрываемых вкладок компонент x-tabs будет работать сразу же. Тем не менее, если нам нужны закрываемые вкладки, которые можно отслеживать в Angular, нам нужно управлять неким состоянием и позволить Angular отслеживать рендеринг компонентов x-tab. Сначала мы изменим наш шаблон приложения и добавим в него новый набор вкладок (для этого урока) и с помощью ngFor сгенерируем их из массива объектов (tabObjects).

<x-tabs (tabclosed)="onStatefulTabClosed($event)">
  <x-tab *ngFor="let tab of tabObjects; let i = index" #statefulTab
 [attr.data-index]="i" [title]="tab.title" [closable]="tab.closable">
 <div>
 <h3>{{ tab.pane.title }}</h3>
 </div>
  </x-tab>
</x-tabs>

Затем мы добавим в компонент массив tabObjects, коллекцию для хранения наших элементов statefulTab, а также обработчик события onStatefulTabClosed:

import { Component, ViewChildren, QueryList, ElementRef } from '@angular/core';
 
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  tabObjects = [
 {
 title: 'Tab 01',
 closable: true,
 pane: {
 title: 'Tab 01 Content'
 }
 },
 {
 title: 'Tab 02',
 closable: false,
 pane: {
 title: 'Tab 02 Content'
 }
 }
  ];
 
  @ViewChildren('tab') tabs: QueryList<ElementRef>;
  @ViewChildren('statefulTab') statefulTabs: QueryList<ElementRef>;
 
  onTabClosed({ detail: component }) {
 console.log(component);
  }
 
  onStatefulTabClosed(event) {
 event.preventDefault();
 const component = event.detail;
 this.tabObjects.splice(component.dataset.index, 1);
  }
}

Так как мы генерируем компоненты x-tab из массива tabObjects, любые изменения в нем внутри обработчика события вызовут повторный рендеринг. Также нам нужно отключить стандартное поведение события tabclosed (удаление x-tab и li), так как Angular будет делать это автоматически. Если заглянуть в Angular после клика по кнопке закрытия первой вкладки в наших stateful вкладках, можно увидеть, что Angular обновляет коллекцию statefulTabs, чтобы она совпадала с текущим состоянием компонента:

Использование веб-компонентов в Angular

Заключение

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

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

Автор: Bryan Forbes

Источник: https://www.sitepen.com/

Редакция: Команда webformyself.

Практический курс по созданию веб-приложения на Angular4

Станьте профессиональным веб-разработчиком, создавая востребованные веб-приложения на Angular4.

Узнать подробнее
Самые свежие новости IT и веб-разработки на нашем Telegram-канале

Angular 4 с Нуля до Профи

Angular 4 - полное руководство для современной веб-разработки

Научиться

Метки:

Похожие статьи:

Комментарии Вконтакте:

Комментарии Facebook:

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Я не робот.

Spam Protection by WP-SpamFree