Эта статья — перевод оригинальной статьи Luis Aviles «How to integrate Web Components using Lit in Angular«
Также я веду телеграм канал “Frontend по-флотски”, где рассказываю про интересные вещи из мира разработки интерфейсов.
Вступление
В этом руководстве я объясню необходимые шаги для интеграции веб-компонентов в Angular. Спойлер: Вы можете найти исходный код демонстрационного проекта в конце.
![](https://habrastorage.org/getpro/habr/upload_files/41c/e2f/9fd/41ce2f9fd2ad1d9538667095ea69d8d1.png)
Настройка проекта
В вашей локальной среде должны быть установлены следующие инструменты:
-
Node.js. Желательно последняя версия LTS.
-
Менеджер пакетов. Вы можете использовать npm или yarn. В этом руководстве будет использоваться npm.
Создание проекта Angular
Давайте создадим проект с нуля с помощью Angular CLI.
ng new angular-lit-web-components --routing --prefix corp --style css --skip-tests
Эта команда инициализирует базовый проект с использованием некоторых параметров конфигурации:
-
--routing
. Будет создан модуль маршрутизации. -
--prefix corp
. Он определяет префикс, который будет применяться к селекторам для созданных компонентов (в данном случаеcorp
). Значение по умолчанию —app
. -
--style css
. Расширение файла стилей. -
--skip-tests
. Это позволяет избежать генерации файлов.spec.ts
, которые используются для тестирования.
Установка Lit
Lit — это простая библиотека для создания быстрых и легких веб-компонентов.
Lit доступен через npm, давайте установим его как новую зависимость для текущего проекта.
npm install --save lit
Дополнительную информацию о Lit можно найти здесь.
Установка Web Components Polyfills
Есть несколько способов установить полифилы веб-компонентов. В этом случае мы установим его с помощью npm.
npm install --save @webcomponents/webcomponentsjs
Затем вы можете использовать webcomponents-loader.js
, который позволяет загружать минимальный пакет полифиллов.
Обновляем Angular конфиг
Вы можете загрузить полифиллы с помощью тега <script> в файл index.html. Однако в Angular это можно сделать путем добавления новых конфигураций ресурсов и скриптов в файл angular.json следующим образом:
"architect": { "build": { ... "options": { ... "assets": [ "src/favicon.ico", "src/assets", { "glob": "{*loader.js,bundles/*.js}", "input": "node_modules/@webcomponents/webcomponentsjs", "output": "node_modules/@webcomponents/webcomponentsjs" } ], "scripts": [ "node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js" ] ... }, "configurations": { ... }, ... }, }
И входные, и выходные свойства должны относиться к корневому пути проекта. То же самое и с импортированным скриптом.
Создание веб-компонентов с использованием Lit
Настройка проекта завершена, и теперь пора создать наш первый веб-компонент с использованием Lit.
Давайте создадим папку src/web-components/card-user
, а затем создадим два файла: card-user.ts
и user.ts
.
Файл user.ts
будет определять общую модель, используемую реализацией веб-компонента и проектом Angular:
// user.ts export interface User { id: number; fullName: string; role: string; avatar?: string; }
Затем давайте напишем код для нашего веб-компонента в файле card-user.ts
:
// card-user.ts import { LitElement, html, css } from 'lit'; import { property, customElement } from 'lit/decorators.js'; import { User } from './user'; @customElement('card-user') export class CardUser extends LitElement { static styles = css` :host { display: block; } .card { box-shadow: 0 10px 10px 0 rgba(0, 0, 0, 0.5); max-width: 160px; } .card-content { padding: 10px; } `; @property({ type: Object }) user?: User = { id: 0, fullName: 'Luis Aviles', role: 'Software Engineer', }; render() { if (this.user === undefined) { return ''; } return html` <div class="card"> <img width="160px" src=${this.user.avatar ? this.user.avatar : 'assets/images/avatar.png'} /> <div class="card-content"> <h4>${this.user.fullName}</h4> <p>${this.user.role}</p> <button @click=${this.handleEdit}>Edit</button> </div> </div> `; } private handleEdit() { this.dispatchEvent( new CustomEvent<User>('edit', { detail: this.user, }) ); } }
Класс CardUser
определяет кастомный элемент как новый виджет для нашего проекта.
-
Декоратор
@customElement
позволяет определять компонент, используя для него имя:card-user
. -
Поле
static styles
определяет стили для компонента с литерала шаблонаcss
. -
Декоратор
@property
, который позволяет объявлять свойства кастомного элемента в удобном виде. -
Метод рендеринга возвращает содержимое HTML через литерал шаблона
html
. Эта функция будет вызываться каждый раз при изменении свойства пользователя.
Вы можете узнать больше о том, как создать компонент с помощью Lit здесь.
Использование веб-компонентов в Angular
Импортируем веб-компонент
Перед использованием любого веб-компонента в Angular, нам необходимо импортировать его следующим образом:
// app.component.ts import { Component } from '@angular/core'; import '../web-components/card-user/card-user'; // <-- import the web component @Component({ selector: 'corp-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], }) export class AppComponent {}
Используем кастомный элемент
Следующим шагом будет использование нового кастомного элемента <card-user>
как части шаблона. В этом случае давайте использовать его в нашем файле app.component.html
:
<card-user></card-user>
После сохранения этих изменений вы можете обнаружить ошибку в консоле (место, где вы запускаете ng serve).
Error: src/app/app.component.html:1:1 - error NG8001: 'card-user' is not a known element: 1. If 'card-user' is an Angular component, then verify that it is part of this module. 2. If 'card-user' is a Web Component, add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message. 1 <card-user></card-user> ~~~~~~~~~~~ src/app/app.component.ts:7:16 7 templateUrl: './app.component.html', ~~~~~~~~~~~~~~~~~~~~~~ Error occurs in the template of component AppComponent.
К счастью, предыдущее сообщение об ошибке достаточно понятно нам говорит, что нам нужно изменить файл app.module.ts
.
// app.module.ts import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; @NgModule({ declarations: [AppComponent], imports: [BrowserModule, AppRoutingModule], providers: [], bootstrap: [AppComponent], schemas: [CUSTOM_ELEMENTS_SCHEMA], }) export class AppModule {}
Важная часть здесь — импортировать CUSTOM_ELEMENTS_SCHEMA
из пакета @angular/core
, а затем использовать его в свойстве schemas
. Вы можете найти больше информации об этом здесь.
Сохраните изменения еще раз, и волшебство произойдет 🙂
![](https://habrastorage.org/getpro/habr/upload_files/fc3/48c/06e/fc348c06e0e439c107f322b2bbeb1d82.png)
Использование Property Binding
Удобно знать, что мы можем не только импортировать внешние компоненты в наше приложение, но и использовать привязку свойств.
Для этого определим свойство user
в файле app.component.ts
:
// app.component.ts export class AppComponent { user: User = { id: 2, fullName: 'Luis', role: 'Software Engineer', avatar: 'https://luixaviles.com/images/avatar@2x.png', }; }
Затем мы можем обновить связанный шаблон и использовать квадратные скобки для привязки свойства:
<card-user [user]="user"></card-user>
Более того, вы можете создать массив пользователей, чтобы иметь возможность отображать их, используя другие полезные функции из нашего любимого фреймворка, например, структурная директива *ngFor
.
<card-user *ngFor="let user of users" [user]="user"></card-user>
Использование Event Binding
Пришло время слушать действия пользователя и реагировать на них через привязку событий в Angular. Как вы видели ранее, компонент corp-user
может отправлять событие edit
после нажатия кнопки «Изменить».
На этот раз воспользуемся круглыми скобками для привязки метода:
<card-user *ngFor="let user of users" [user]="user" (edit)="edit($event)"></card-user>
Наконец, давайте создадим метод редактирования в нашем компоненте.
// app.component.ts //... export class AppComponent { //... edit(event: Event) { const user = (event as CustomEvent<User>).detail; console.log('Edit user', user); } }
Метод edit
получает обобщенный Event
. Хотя кастомный элемент отправил объект User
через CustomEvent
. Затем мы можем использовать синтаксический оператор as
из TypeScript и получить к нему доступ с помощью свойства detail. На следующем снимке экрана показаны результаты в консоли браузера.
![](https://habrastorage.org/getpro/habr/upload_files/a8a/757/a75/a8a757a75b1e9e8c232046b79c478a0d.png)
Исходный код проекта
Вы можете найти полный код в этом репозитории GitHub: angular-lit-web-components. Не забудьте поставить звездочку ⭐️ и поэкспериментировать с кодом.
ссылка на оригинал статьи https://habr.com/ru/articles/583924/
Добавить комментарий