Implementamos componentes angulares em React, Vue e até jQuery, se você quiser

Se você encontrou um componente interessante em npm, mas com o prefixo ng, ngx, angular e assim por diante, não se preocupe com isso. Existem muitas soluções para obter esse componente. Neste artigo, consideraremos uma solução oficialmente suportada pela equipe angular, a saber, elementos angulares.

Para praticar, escolha qualquer componente em Awesome Angular .

Eu escolhi um avatar simples, mas muito interessante - ngx . Que, por sua vez, exibe avatares de várias redes sociais ou simplesmente exibe as iniciais do usuário.
Algo assim:


E ele tem uma API simples, aqui está um pequeno exemplo:

<ngx-avatar facebookId="1508319875"></ngx-avatar> <ngx-avatar src="assets/avatar.jpg"></ngx-avatar> <ngx-avatar name="John Doe"></ngx-avatar> 

E assim, crie um projeto Angular para isso e conecte a biblioteca.

 ng new avatar-lib --minimalN npm i ngx-avatar --save 

Conecte o pacote ao nosso módulo.

 import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; // Import your AvatarModule import { AvatarModule } from 'ngx-avatar'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, // Specify AvatarModule as an import AvatarModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { } 

Agora vamos criar um componente simples, porque por padrão o `AvatarModule` não exporta seu único componente.

 ng gc avatar 

 import { Component, ViewEncapsulation, Input } from '@angular/core'; @Component({ selector: 'app-avatar', template: ` <ngx-avatar [name]="name"></ngx-avatar> `, styles: [], encapsulation: ViewEncapsulation.ShadowDom }) export class AvatarComponent { @Input() name: string; constructor() { } } 

Para simplificar, usamos apenas um dos parâmetros de entrada.

Criaremos um componente universal a partir de tudo isso. Para que nossos elementos funcionem, você precisa adicionar elementos angulares ao nosso projeto.

 ng add @angular/elements 

Entre outras coisas, este comando também incluirá na seção de scripts uma versão lite para registrar os Elementos Personalizados.

 "scripts": [{ "input": "node_modules/document-register-element/build/document-register-element.js" }] 

O app.module.ts resultante:

 import { BrowserModule } from '@angular/platform-browser'; import { NgModule, Injector } from '@angular/core'; import { createCustomElement } from '@angular/elements'; import { AvatarComponent } from './avatar.component'; import { AvatarModule } from 'ngx-avatar'; @NgModule({ declarations: [AvatarComponent], imports: [AvatarModule, BrowserModule], entryComponents: [AvatarComponent] }) export class AppModule { constructor(private injector: Injector) { //    Angular Element const avatarComponent = createCustomElement(AvatarComponent, { injector }); //     customElements.define('avatar-lib', avatarComponent); } ngDoBootstrap() {} } 

Ótimo! Agora precisamos coletar tudo isso de bom. Para fazer isso, crie seu próprio coletor que compactará nosso componente em um arquivo js:

 const fs = require('fs-extra'); const concat = require('concat'); (async function build() { const files = [ './dist/avatar-lib/runtime.js', './dist/avatar-lib/polyfills.js', './dist/avatar-lib/scripts.js', './dist/avatar-lib/main.js' ]; await fs.ensureDir('elements'); await concat(files, 'elements/avatar-lib.js'); })(); 

Está tudo pronto! resta apenas coletar. Adicione esse script ao nosso package.json.

 "build:elements": "ng build --prod --output-hashing none && node build.js" 

Bem, é isso! Temos um arquivo js `avatar-lib.js` pesando ~ 221kB e ~ 60kb no gzip. Naturalmente, muitos mais estão incluídos aqui com angular / core. O próprio ngx-avatar pesa cerca de 16,8kB e 5,4kB em gzip. Para reduzir bastante o peso do avatar-lib.js, precisaríamos do Ivy Compiler, mas este é um tópico para outro artigo. (Espero que Ivy seja lançada nesse momento ou colecionarei manualmente o que já está disponível).

O que os elementos angulares nos deram?

Esta é apenas uma API útil para implementar componentes da Web. De fato, alguém poderia ficar sem ele. Veja o que você poderia fazer anteriormente: um artigo de Jia Li (acompanha ativamente o Zone.js agora) .

Incorporamos nosso componente em outras estruturas.

Primeiro no Vue. Nós nos conectamos de qualquer maneira conveniente para você e inserimos avatar-lib no modelo, transferimos os dados através de vue bings padrão.

 <avatar-lib :name = 'myName'></avatar-lib> 

Também seria possível organizar eventos de saída.

Demonstração do Vue: https://github.com/Jamaks/angular-element/tree/master/ang-el-vue

É hora de reagir! Tudo é tão simples:

 <avatar-lib name = {this.myName}></avatar-lib> 

Demonstração ao reagir

Bem, em geral, o projeto

Quanto ao suporte ao navegador no momento:

https://angular.io/guide/elements#browser-support-for-custom-elements
https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry/define

Obviamente, você decide se deve usar esse método de implementação. Eu gostaria que os componentes da interface do usuário não fossem anexados a nada e não tivessem sufixos semelhantes: ng-, ngx-, v-, react-, rc- e assim por diante.

Bônus!

Inspirado no tamanho do componente (ngx-avatar), ainda tentei alimentar o ngtsc, ngcc e montá-lo usando o rollup. Mas as tentativas foram malsucedidas, pois o componente selecionado exigia muitos módulos externos. Desesperado, parecia um pouco desse componente e os resultados me surpreenderam agradavelmente - no momento (7.1.2), a biblioteca tinha ~ 96kb e ~ 26kb no gzip. Naturalmente, havia muitas dependências e minha configuração de rollup deixa muito a desejar. Mas ainda assim, este não é o 3kb que nos foi mostrado durante a apresentação de Ivy. Resta esperar quando eles implantam o ngcc no Webpack (cli) e escrevem a documentação.

Você também pode encontrar pequenas experiências e especialistas do mundo angular aqui .

Source: https://habr.com/ru/post/pt432664/


All Articles