Betten Sie Winkelkomponenten in React, Vue und sogar in jQuery ein, wenn Sie möchten

Published on December 10, 2018

Betten Sie Winkelkomponenten in React, Vue und sogar in jQuery ein, wenn Sie möchten

Wenn Sie in npm eine coole Komponente finden, aber mit dem Präfix ng, ngx, angle usw., dann sollten Sie sich darüber nicht aufregen. Es gibt viele Lösungen, um diese Komponente für Sie verfügbar zu machen. In diesem Artikel betrachten wir eine Lösung, die vom Angular Team offiziell unterstützt wird, nämlich Angular Elements.

Wählen Sie zum Üben eine beliebige Komponente aus Awesome Angular .

Ich habe einen einfachen, aber sehr interessanten  ngx-avatar gewählt . Das wiederum zeigt Avatare aus verschiedenen sozialen Netzwerken oder einfach die Initialen des Benutzers.
Etwas wie das:


Und er hat eine einfache API, hier ein kleines Beispiel:

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

Und so werden wir für dieses Angular das Projekt erstellen und die Bibliothek verbinden.

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

Verbinden Sie das Paket mit unserem Modul.

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 { }

Erstellen Sie nun eine einfache Komponente, da AvatarModule seine einzige Komponente standardmäßig nicht nach außen exportiert.

ng g c 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() { }
}

Zur Vereinfachung haben wir nur einen der Eingabeparameter verwendet.

Erstellen Sie daraus eine universelle Komponente. Damit unsere Elemente funktionieren können, müssen Sie unserem Projekt Winkelelemente hinzufügen.

ng add @angular/elements

Dieser Befehl enthält unter anderem auch eine leichte Version für die Registrierung von benutzerdefinierten Elementen.

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

Das resultierende app.module.ts:

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() {}
}

Großartig! Jetzt müssen wir all das Zeug sammeln. Erstellen Sie dazu einen eigenen Collector, der unsere Komponente in eine js-Datei packt:

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');
})();

Alles ist fertig! es bleibt nur noch zu sammeln. Fügen Sie dieses Skript unserer package.json hinzu.

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

Nun, das ist es! Es stellte sich heraus, dass wir eine solche js-Datei `avatar-lib.js` mit einem Gewicht von ~ 221kB und ~ 60kb in gzip haben. Natürlich sind viele weitere mit Winkel / Kern enthalten. Der ngx-Avatar selbst wiegt etwa 16,8 kB und 5,4 kB in gzip. Um das Gewicht von avatar-lib.js erheblich zu reduzieren, benötigen wir einen Ivy-Compiler. Dies ist jedoch ein Thema für einen anderen Artikel. (Ich hoffe, bis zu diesem Moment werde ich Ivy freigeben, oder ich werde es manuell abholen, was jetzt verfügbar ist).

Was haben uns die Winkelelemente gegeben?

Dies ist nur eine praktische API für die Implementierung von Webkomponenten. Man könnte sogar darauf verzichten. Sehen Sie, was Sie früher hätten tun können: der Artikel von Jia Li (jetzt aktiv mit Zone.js verbunden) .

Wir implementieren unsere Komponente in anderen Frameworks.

Zuerst in Vue. Wir stellen für Sie eine beliebige Verbindung her und fügen in die Vorlage avatar-lib ein. Die Daten werden durch das Standardvue binging weitergeleitet.

<avatar-lib :name = ‘myName’></avatar-lib>

Sie können auch Ausgabe-Events organisieren.

Demo auf Vue: https://github.com/Jamaks/angular-element/tree/master/ang-el-vue

Es ist Zeit für React! Immer noch so einfach:

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

Demo reagieren

Nun, im Allgemeinen das Projekt

Wie für die Browserunterstützung im Moment:

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

Selbstverständlich müssen Sie diese Implementierungsmethode verwenden oder nicht. Ich möchte, dass die UI-Komponenten an nichts gebunden sind und keine ähnlichen Suffixe haben: ng-, ngx-, v-, reag-, rc- und so weiter.

Bonus!

Inspiriert von der Größe der Komponente (ngx-avatar) habe ich versucht, alle ngtsc, ngcc zu füttern und dann mit Rollup zu erstellen. Die Versuche waren jedoch erfolglos, da für die ausgewählte Komponente viele externe Module erforderlich waren. Verzweifelt machte ich einige Ähnlichkeiten mit dieser Komponente und die Ergebnisse waren angenehm überrascht - im Moment (7.1.2) stellte sich heraus, dass die Bibliothek ~ 96kb und ~ 26kb in gzip ausfiel. Natürlich gingen viele Abhängigkeiten dahin, und meine Rollup-Konfiguration lässt zu wünschen übrig. Dies ist jedoch immer noch nicht 3kb, was wir bei der Präsentation von Ivy gezeigt haben. Es bleibt abzuwarten, wenn ngcc im Webpack (cli) implementiert ist und die Dokumentation geschrieben ist.

Nur ein kleines Experiment und Innenseite von Angular können die Welt auf den Link finden .