Heim > Web-Frontend > CSS-Tutorial > Aufbau interoperabler Webkomponenten, die funktionieren

Aufbau interoperabler Webkomponenten, die funktionieren

尊渡假赌尊渡假赌尊渡假赌
Freigeben: 2025-03-13 10:05:10
Original
462 Leute haben es durchsucht

Aufbau interoperabler Webkomponenten, die funktionieren

Diejenigen von uns, die mehr als ein paar Jahre Webentwickler waren, haben wahrscheinlich Code mit mehr als einem JavaScript -Framework geschrieben. Mit all den Auswahlmöglichkeiten - reagieren, Sufle, Vue, Angular, Solid - es ist so gut wie unvermeidlich. Eines der frustrierenderen Dinge, mit denen wir uns bei der Arbeit in Frameworks befassen müssen, ist die Wiederherstellung all dieser UI-Komponenten auf niedriger Ebene: Schaltflächen, Registerkarten, Dropdowns usw. Besonders frustrierend ist, dass wir sie normalerweise in einem Framework definiert haben, sagen wir, reagieren, aber müssen sie dann neu schreiben, wenn wir etwas in Svelte bauen wollen. Oder Vue. Oder fest. Und so weiter.

Wäre es nicht besser, wenn wir diese UI-Komponenten auf niedriger Ebene einmal auf eine agnostische Weise definieren und sie dann zwischen Frameworks wiederverwenden könnten? Natürlich würde es! Und wir können; Webkomponenten sind der Weg. Dieser Beitrag zeigt Ihnen wie.

Ab sofort fehlt die SSR -Geschichte für Webkomponenten. Declarative Shadow DOM (DSD) ist, wie eine Webkomponente serverseitig gerendert wird, aber nach diesem Schreiben wird sie jedoch nicht in Ihre bevorzugten Anwendungsframeworks wie Next, Remix oder Sveltekit integriert. Wenn dies eine Voraussetzung für Sie ist, überprüfen Sie unbedingt den neuesten Status von DSD. Aber ansonsten, wenn SSR nicht etwas nicht verwendet, lesen Sie weiter.

Erstens ein Kontext

Webkomponenten sind im Wesentlichen HTML-Elemente, die Sie selbst definieren, wie oder was auch immer, von Grund auf. Sie sind hier bei CSS-Tricks abgedeckt (einschließlich einer umfangreichen Serie von Caleb Williams und einer von John Rhea), aber wir werden kurz den Prozess durchlaufen. Im Wesentlichen definieren Sie eine JavaScript -Klasse, erben sie von htmlelement und dann die Eigenschaften, Attribute und Stile, die die Webkomponente hat, und natürlich das Markup, das sie letztendlich Ihren Benutzern übergeben wird.

Es ist aufregend, benutzerdefinierte HTML -Elemente zu definieren, die nicht an eine bestimmte Komponente gebunden sind. Diese Freiheit ist aber auch eine Einschränkung. Wenn Sie unabhängig von einem JavaScript -Framework existieren, können Sie nicht wirklich mit diesen JavaScript -Frameworks interagieren. Stellen Sie sich eine React -Komponente vor, die einige Daten abruft und dann eine andere React -Komponente macht und die Daten weitergibt. Dies würde nicht wirklich als Webkomponente funktionieren, da eine Webkomponente nicht weiß, wie man eine React -Komponente rendert.

Webkomponenten sind besonders als Blattkomponenten ausgestattet. Blattkomponenten sind das Letzte, was in einem Komponentenbaum gerendert werden kann. Dies sind die Komponenten, die einige Requisiten erhalten und eine Benutzeroberfläche rendern. Dies sind nicht die Komponenten, die in der Mitte Ihres Komponentenbaums sitzen, Daten übergeben, Kontext einstellen usw. - nur reine UI -Teile, die gleich aussehen, unabhängig davon, welches JavaScript -Framework den Rest der App mit Strom versorgt.

Die Webkomponente, die wir bauen

Anstatt etwas Langweiliges (und Gemeinsames) zu bauen, wie ein Knopf, bauen wir etwas anderes auf. In meinem letzten Beitrag befassten wir uns mit der Verwendung von verschwommenen Bildvoransichten, um den Inhaltsausfall zu verhindern, und bieten eine anständige Benutzeroberfläche für Benutzer, während unsere Bilder laden. Wir haben uns Base64 angesehen, um eine verschwommene, degradierte Version unserer Bilder zu kodieren und dies in unserer Benutzeroberfläche zu zeigen, während das reale Bild geladen wurde. Wir haben uns auch mithilfe eines Tools namens Blurhash unglaublich kompakte, verschwommene Vorschau angesehen.

Dieser Beitrag hat Ihnen gezeigt, wie Sie diese Voransichten generieren und in einem React -Projekt verwenden können. In diesem Beitrag werden Sie angezeigt, wie Sie diese Voransichten aus einer Webkomponente verwenden, damit sie von jedem JavaScript -Framework verwendet werden können.

Aber wir müssen gehen, bevor wir rennen können, also werden wir zuerst etwas Triviales und Dummes durchgehen, um genau zu sehen, wie Webkomponenten funktionieren.

Alles in diesem Beitrag erstellt Vanilla -Webkomponenten ohne Werkzeuge. Das bedeutet, dass der Code ein bisschen Kesselplatte hat, sollte jedoch relativ einfach zu befolgen sein. Tools wie Lit oder Schablone sind zum Erstellen von Webkomponenten konzipiert und können zum Entfernen eines Großteils dieser Kesselplatte verwendet werden. Ich fordere Sie auf, sie zu überprüfen! Aber für diesen Beitrag werde ich etwas mehr Kesselplatte bevorzugen, um keine andere Abhängigkeit vorzustellen und zu lehren.

Eine einfache Gegenkomponente

Erstellen wir die klassische „Hello World“ von JavaScript -Komponenten: eine Theke. Wir werden einen Wert und eine Schaltfläche rendern, die diesen Wert erhöht. Einfach und langweilig, aber es lässt uns die einfachste Webkomponente ansehen.

Um eine Webkomponente zu erstellen, besteht der erste Schritt darin, eine JavaScript -Klasse zu erstellen, die von htmlelement ererbt:

 Der Klassenzähler erweitert Htmlelement {}
Nach dem Login kopieren

Der letzte Schritt besteht darin, die Webkomponente zu registrieren, aber nur, wenn wir sie noch nicht registriert haben:

 if (! CustomElements.get ("Counter-WC")) {
  CustomElements.define ("Counter-WC", The Counter);
}
Nach dem Login kopieren

Und natürlich rendern es:

 <counter-wc> </counter-wc>
Nach dem Login kopieren

Und alles dazwischen ist, dass wir die Webkomponente tun, was wir wollen. Eine übliche Lebenszyklusmethode ist ConnectedCallback, die ausfeuert, wenn unsere Webkomponente zum DOM hinzugefügt wird. Wir könnten diese Methode verwenden, um alle Inhalte zu rendern, die wir möchten. Denken Sie daran, dass dies eine JS -Klasse ist, die von HTMLElement erbt, was bedeutet, dass unser Wert das Webkomponentenelement selbst ist, mit all den normalen DOM -Manipulationsmethoden, die Sie bereits kennen und lieben.

Am einfachsten könnten wir Folgendes tun:

 Der Klassenzähler erweitert Htmlelement {
  connectedCallback () {
    this.innerhtml = "<div style="'color:" green> hey </div>";
  }
}

if (! CustomElements.get ("Counter-WC")) {
  CustomElements.define ("Counter-WC", The Counter);
}
Nach dem Login kopieren

… Was wird gut funktionieren.

Hinzufügen von echten Inhalten

Fügen wir einige nützliche, interaktive Inhalte hinzu. Wir brauchen eine , um den aktuellen Zahlenwert und eine zu halten, um den Zähler zu erhöhen. Im Moment erstellen wir diesen Inhalt in unserem Konstruktor und fügen ihn an, wenn sich die Webkomponente tatsächlich im DOM befindet:

 constructor () {
  super();
  const container = document.createelement ('div');

  this.valspan = document.createelement ('span');

  const increment = document.createelement ('button');
  Increment.InNerText = 'Increment';
  increment.adDeVentListener ('klick', () => {
    this.#value = this.#currentValue 1;
  });

  Container.AppendChild (this.valpan);
  Container.AppendChild (document.Createelement ('br'));
  Container.AppendChild (Inkrement);

  this.container = Container;
}

connectedCallback () {
  this.appendChild (this.container);
  this.update ();
}
Nach dem Login kopieren

Wenn Sie sich von der manuellen DOM -Erstellung wirklich ausgedacht haben, denken Sie daran, dass Sie Innerhtml festlegen oder sogar ein Vorlagenelement als statische Eigenschaft Ihrer Web -Komponentenklasse erstellen, ihn klonen und den Inhalt für neue Webkomponenteninstanzen einfügen können. Es gibt wahrscheinlich einige andere Optionen, an die ich nicht denke, oder Sie können immer ein Webkomponenten -Framework wie Lit oder Schablone verwenden. Aber für diesen Beitrag werden wir es weiterhin einfach halten.

Wenn wir weitermachen, brauchen wir eine einsetzbare Eigenschaft der JavaScript -Klasse mit dem Namen Value

 #CurrentValue = 0;

Setzen Sie #Value (Val) {
  Dies.#currentValue = val;
  this.update ();
}
Nach dem Login kopieren

Es ist nur eine Standard -Klasseneigenschaft mit einem Setter, zusammen mit einer zweiten Eigenschaft, um den Wert zu halten. Eine lustige Wendung ist, dass ich die Eigenschaftssyntax der privaten JavaScript -Klasse für diese Werte verwende. Das bedeutet, dass niemand außerhalb unserer Webkomponente diese Werte jemals berühren kann. Dies ist Standard -JavaScript, das in allen modernen Browsern unterstützt wird. Haben Sie also keine Angst, es zu verwenden.

Oder nennen Sie es _Value, wenn Sie es vorziehen. Und schließlich unsere Update -Methode:

 aktualisieren() {
  this.valspan.inNertext = this.#currentValue;
}
Nach dem Login kopieren

Es funktioniert!

Offensichtlich ist dies kein Code, den Sie im Maßstab beibehalten möchten. Hier ist ein komplettes Beispiel, wenn Sie einen genaueren Blick möchten. Wie ich bereits sagte, sind Tools wie Lit und Schablone so gestaltet, dass sie dies einfacher machen.

Etwas mehr Funktionalität hinzufügen

Dieser Beitrag ist kein tiefes Eintauchen in Webkomponenten. Wir werden nicht alle APIs und Lebenszyklen abdecken. Wir werden nicht einmal Schattenwurzeln oder Slots abdecken. Es gibt endlose Inhalte zu diesen Themen. Mein Ziel hier ist es, eine anständige Einführung zu bieten, um ein gewisses Interesse zu wecken, zusammen mit einigen nützlichen Anleitungen zur tatsächlichen Verwendung von Webkomponenten mit den beliebten JavaScript -Frameworks, die Sie bereits kennen und lieben.

Lassen Sie uns zu diesem Zweck unsere Counter -Webkomponente ein wenig verbessern. Lassen Sie es uns ein Farbattribut akzeptieren, um die Farbe des angezeigten Werts zu steuern. Lassen Sie uns auch eine Increment -Eigenschaft akzeptieren, sodass die Verbraucher dieser Webkomponente sie jeweils um 2, 3, 4 erhöhen können. Um diese Zustandsänderungen voranzutreiben, verwenden wir unseren neuen Zähler in einer schlanken Sandkiste - wir werden ein wenig reagieren.

Wir beginnen mit derselben Webkomponente wie zuvor und fügen ein Farbattribut hinzu. Um unsere Webkomponente so zu konfigurieren, um ein Attribut zu akzeptieren und darauf zu reagieren, fügen wir eine statische Eigenschaft beobachtete Eigenschaft hinzu, die die Attribute zurückgibt, für die unsere Webkomponente hört.

 static beobachteteAttributes = ["Farbe"];
Nach dem Login kopieren

Mit diesem vorhanden können wir eine AttributechangeDcallback -Lebenszyklusmethode hinzufügen, die ausgeführt wird, wenn eine der in beobachteten ATTRIBUTes aufgeführten Attribute festgelegt oder aktualisiert wird.

 AttributEchangedCallback (Name, OldValue, NewValue) {
  if (name === "Farbe") {
    this.update ();
  }
}
Nach dem Login kopieren

Jetzt aktualisieren wir unsere Update -Methode, um sie tatsächlich zu verwenden:

 aktualisieren() {
  this.valspan.Innertext = this._currentValue;
  this.valspan.style.color = this.getAttribute ("Farbe") || "Schwarz";
}
Nach dem Login kopieren

Zuletzt fügen wir unsere Increment -Eigenschaft hinzu:

 Inkrement = 1;
Nach dem Login kopieren

Einfach und bescheiden.

Verwenden der Zählerkomponente in Svelte

Lassen Sie uns das verwenden, was wir gerade gemacht haben. Wir werden in unsere Sufle -App -Komponente gehen und so etwas hinzufügen:

 <script>
  lass color = "rot";
</script>

<styles>
  hauptsächlich {
    Text-Align: Mitte;
  }


<main>
  <select bind: value="{color}">
    <option value="rot"> rot </option>
    <option value="Green"> Green </option>
    <option value="Blue"> Blue </option>
  </select>

  <counter wc color="{color}"> 
</counter></main></styles>
Nach dem Login kopieren

Und es funktioniert! Unsere Zähler rendern, Inkremente und die Dropdown -Rendite aktualisieren die Farbe. Wie Sie sehen können, rendern wir das Farbattribut in unserer schlanken Vorlage und wenn sich der Wert ändert, übernimmt Svelte das Beinwerk, SetAttribute auf unserer zugrunde liegenden Webkomponenteninstanz aufzurufen. Hier gibt es nichts Besonderes: Dies ist das gleiche, was es für die Attribute eines HTML -Elements bereits tut.

Die Dinge werden mit der Increment -Requisite ein bisschen interessant. Dies ist kein Attribut in unserer Webkomponente. Es ist eine Requisite in der Klasse der Webkomponente. Das bedeutet, dass es in der Instanz der Webkomponente festgelegt werden muss. Tragen Sie mit mir, da die Dinge ein wenig viel einfacher werden.

Zunächst fügen wir unserer schlanken Komponente einige Variablen hinzu:

 Sei inkrement = 1;
lass wcinstance;
Nach dem Login kopieren

In unserem Kraftpaket einer Zählerkomponente können Sie um 1 oder 2 erhöht werden:

 <schaltfl auf: klick="{()"> inkrement = 1}> inkrement 1 
<schaltfl auf: klick="{()"> inkrement = 2}> inkrement 2 </schaltfl></schaltfl>
Nach dem Login kopieren

Theoretisch müssen wir jedoch die tatsächliche Instanz unserer Webkomponente erhalten. Dies ist dasselbe, was wir immer tun, wenn wir einen Schiedsrichter mit React hinzufügen. Mit Sufle ist es eine einfache Bindung: diese Richtlinie:

 <counter-wc bind: this="{wcinstance}" color="{color}"> </counter-wc>
Nach dem Login kopieren

In unserer schlanken Vorlage hören wir nun auf Änderungen an der Inkrementvariablen unserer Komponente und setzen die zugrunde liegende Webkomponenteneigenschaft.

 $: {
  if (wcinstance) {
    wcinstance.increment = Increment;
  }
}
Nach dem Login kopieren

Sie können es bei dieser Live -Demo testen.

Wir möchten dies offensichtlich nicht für jede Webkomponente oder Requiente tun, die wir verwalten müssen. Wäre es nicht schön, wenn wir in Markup, wie wir es normalerweise für Komponenten -Requisiten tun, nur das Inkrement in unserer Webkomponente einstellen und sie, wissen Sie, einfach nur für die Arbeit haben? Mit anderen Worten, es wäre schön, wenn wir alle Verwendungen von WCInstance löschen und stattdessen diesen einfacheren Code verwenden könnten:

 <counter-wc increment="{increment}" color="{color}"> </counter-wc>
Nach dem Login kopieren

Es stellt sich heraus, dass wir können. Dieser Code funktioniert; Svelte kümmert sich um all diese Beinarbeit für uns. Probieren Sie es in dieser Demo aus. Dies ist ein Standardverhalten für so ziemlich alle JavaScript -Frameworks.

Warum habe ich Ihnen die manuelle Möglichkeit zum Festlegen der Requisite der Webkomponente gezeigt? Zwei Gründe: Es ist nützlich zu verstehen, wie diese Dinge funktionieren, und vor einem Moment sagte ich, dass dies für „so ziemlich“ alle JavaScript -Frameworks funktioniert. Es gibt jedoch einen Framework, der, wie wir gerade gesehen haben, nicht unterstützt.

React ist ein anderes Tier

Reagieren. Das beliebteste JavaScript -Framework auf dem Planeten unterstützt keine grundlegende Interop -Interop mit Webkomponenten. Dies ist ein bekanntes Problem, das einzigartig für Reaktionen ist. Interessanterweise wird dies tatsächlich in Reacts experimentellem Zweig festgelegt, aber aus irgendeinem Grund wurde nicht in Version 18 zusammengeführt. Das heißt, wir können den Fortschritt immer noch verfolgen. Und Sie können dies selbst mit einer Live -Demo ausprobieren.

Die Lösung besteht natürlich darin, einen Ref zu verwenden, die Webkomponenteninstanz zu greifen und in Erkrankungen zu steigern, wenn sich dieser Wert ändert. Es sieht so aus:

 React, {usestate, useref, useEffect} aus 'react';
Import './Counter-Wc';

Exportieren Sie Standardfunktionsfunktion app () {
  const [Increment, setIncrement] = usustate (1);
  const [color, setColor] = usustate ('rot');
  const wcref = useref (null);

  useEffect (() => {
    wcref.current.increment = Increment;
  }, [Inkrement]);

  zurückkehren (
    <div>
      <div classname="Increment-Container">
        <button onclick="{()"> setIncrement (1)}> Inkrement nach 1 </button>
        <button onclick="{()"> setIncrement (2)}> Inkrement nach 2 </button>
      </div>

      <select value="{color}" onchange="{(e)"> setColor (e.target.Value)}>
        <option value="rot"> rot </option>
        <option value="Green"> Green </option>
        <option value="Blue"> Blue </option>
      </select>

      <counter wc ref="{wcref}" increment="{increment}" color="{color}"> 
    </counter>
</div>
  );
}
Nach dem Login kopieren
Live -Demo

Wie wir besprochen haben, ist es einfach nicht skalierbar, dies manuell für jede Webkomponenteneigenschaft zu kodieren. Aber alles ist nicht verloren, weil wir ein paar Optionen haben.

Option 1: Verwenden Sie überall Attribute

Wir haben Attribute. Wenn Sie oben auf die React -Demo geklickt haben, funktionierte die Increment -Requisite nicht, aber die Farbe hat sich korrekt geändert. Können wir nicht alles mit Attributen codieren? Leider nein. Attributwerte können nur Zeichenfolgen sein. Das ist hier gut genug und wir könnten mit diesem Ansatz etwas weit kommen. Zahlen wie Inkrement können zu und von Strings konvertiert werden. Wir könnten sogar Objekte JSON Stringify/analysieren. Aber irgendwann müssen wir eine Funktion in eine Webkomponente übergeben, und zu diesem Zeitpunkt wären wir keine Optionen mehr.

Option 2: Wickeln Sie es ein

Es gibt ein altes Sprichwort, dass Sie jedes Problem in der Informatik lösen können, indem Sie ein Maß an Indirektion hinzufügen (mit Ausnahme des Problems zu vieler Indirektion). Der Code zum Festlegen dieser Requisiten ist ziemlich vorhersehbar und einfach. Was ist, wenn wir es in einer Bibliothek verstecken? Die klugen Leute hinter Lit haben eine Lösung. Diese Bibliothek erstellt eine neue React -Komponente für Sie, nachdem Sie ihr eine Webkomponente gegeben haben, und listen Sie die Eigenschaften auf, die sie benötigt. Obwohl ich klug ist, bin ich kein Fan dieses Ansatzes.

Anstatt eine Eins-zu-Eins-Zuordnung von Webkomponenten zu manuell geschaffenen React-Komponenten zu haben, bevorzuge ich nur eine React-Komponente, an die wir unseren Webkomponenten -Tag-Namen übergeben (Gegen-WC in unserem Fall)-zusammen mit allen Attributen und Eigenschaften-und für diese Komponente, um unsere Webkomponente zu rendern, dann den Schiedsrichter hinzuzufügen, dann herauszufinden, was ein Prop und was ist ein Prop und was ist ein Attribut. Das ist meiner Meinung nach die ideale Lösung. Ich kenne keine Bibliothek, die dies tut, aber es sollte unkompliziert sein zu erstellen. Lassen Sie uns es versuchen!

Dies ist die Verwendung , nach der wir suchen:

 <wcwrapper wctag="counter-Wc" increment="{Increment}" color="{color}"></wcwrapper>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

WCTAG ist der Webkomponenten -Tag -Name; Der Rest sind die Eigenschaften und Attribute, die wir weitergeben wollen.

So sieht meine Implementierung aus:

 React, {CreateLement, Useref, uselayoutEffect, Memo} aus 'React';

const _wcwrapper = (props) => {
  const {WCTAG, Kinder, ... restprops} = props;
  const wcref = useref (null);

  useSelayouteffect (() => {
    const wc = wcref.current;

    für (const [Schlüssel, Wert] von Object.Entries (restProps)) {
      if (Schlüssel in WC) {
        if (wc [key]! == value) {
          WC [Schlüssel] = Wert;
        }
      } anders {
        if (wc.getAttribute (Schlüssel)! == value) {
          WC.SetAttribute (Schlüssel, Wert);
        }
      }
    }
  });

  return createLement (WCTAG, {Ref: WCREF});
};

Export const wcwrapper = memo (_wcwrapper);
Nach dem Login kopieren

Die interessanteste Linie ist am Ende:

 return createLement (WCTAG, {Ref: WCREF});
Nach dem Login kopieren

So erstellen wir ein Element, das mit einem dynamischen Namen reagiert. In der Tat ist dies das, was React normalerweise JSX verwandelt. Alle unsere Divs werden in CreateLement ("Div") -Anrufe konvertiert. Wir müssen diese API normalerweise nicht direkt nennen, aber es ist da, wenn wir sie brauchen.

Darüber hinaus möchten wir einen Layout -Effekt ausführen und jede Requisite durchlaufen, die wir an unsere Komponente übergeben haben. Wir durchsuchen alle und prüfen, ob es sich um eine Eigenschaft mit einem in Schach handelt, das das Webkomponenten -Instanzobjekt sowie seine Prototyp -Kette überprüft, die alle Getter/Setzer fangen, die auf dem Klassenprototyp landen. Wenn kein solches Eigentum existiert, wird angenommen, dass es sich um ein Attribut handelt. In beiden Fällen haben wir es nur festgelegt, wenn sich der Wert tatsächlich geändert hat.

Wenn Sie sich fragen, warum wir uselayouteffect anstelle von useEffect verwenden, möchten wir diese Updates sofort ausführen, bevor unser Inhalt wiedergegeben wird. Beachten Sie auch, dass wir kein Abhängigkeitsarray für unsere UseLayouteffect haben. Dies bedeutet, dass wir dieses Update für jeden Render ausführen möchten. Dies kann riskant sein, da React dazu neigt, viel wieder zu rendern. Ich habe dies verbessert, indem ich das Ganze in React.Memo einwickelte. Dies ist im Wesentlichen die moderne Version von React.pureComponent, was bedeutet, dass die Komponente nur dann erneut render wird, wenn sich eine der tatsächlichen Requisiten geändert hat-und überprüft, ob dies über eine einfache Gleichstellungsprüfung geschieht.

Das einzige Risiko ist hier, dass Sie die Aktualisierungen nicht sehen, wenn Sie eine Objekt-Requisite übergeben, die Sie direkt ohne erneut zuordnen, ohne erneut zugewiesen zu werden. Dies ist jedoch sehr entmutigt, insbesondere in der React -Community, also würde ich mir keine Sorgen machen.

Bevor ich weitermachen würde, möchte ich eine letzte Sache rufen. Sie sind vielleicht nicht zufrieden mit dem Aussehen der Verwendung. Auch diese Komponente wird so verwendet:

 <wcwrapper wctag="counter-Wc" increment="{Increment}" color="{color}"></wcwrapper>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Insbesondere gefällt Ihnen möglicherweise nicht, dass Sie den Namen des Webkomponenten-Tags an die -Komponente übergeben und stattdessen das oben genannte @Lit-Labs/React-Paket bevorzugen, das für jede Webkomponente eine neue individuelle React-Komponente erstellt. Das ist total fair und ich möchte Sie ermutigen, alles zu verwenden, mit dem Sie sich am besten wohl fühlen. Aber für mich ist ein Vorteil bei diesem Ansatz, dass es leicht zu löschen ist. Wenn durch ein Wunderreakt die korrekte Webkomponentenhandhabung aus ihrem experimentellen Zweig in das Main Tomorrow zusammenfasst, können Sie den obigen Code daraus ändern:

 <wcwrapper wctag="counter-Wc" increment="{Increment}" color="{color}"></wcwrapper>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

… Dazu:

 <counter wc ref="{wcref}" increment="{increment}" color="{color}"></counter>
Nach dem Login kopieren

Sie könnten wahrscheinlich sogar ein einzelnes Codemod schreiben, um dies überall zu tun, und dann insgesamt löschen. Tatsächlich kratzen Sie das: Eine globale Suche und Ersatz durch eine Regex würde wahrscheinlich funktionieren.

Die Implementierung

Ich weiß, es scheint, als hätte es eine Reise gekostet haben, um hierher zu kommen. Wenn Sie sich erinnern, war unser ursprüngliches Ziel, den in meinem letzten Beitrag betrachteten Bildvorschehrcode zu übernehmen und in eine Webkomponente zu verschieben, damit er in jedem JavaScript -Framework verwendet werden kann. Reacts Fehlen an ordnungsgemäßem Interop fügte der Mischung viele Details hinzu. Aber jetzt, da wir einen angemessenen Griff haben, wie eine Webkomponente erstellt und sie verwendet wird, wird die Implementierung fast antiklimaktisch sein.

Ich werde die gesamte Webkomponente hier fallen lassen und einige der interessanten Teile aufrufen. Wenn Sie es in Aktion sehen möchten, finden Sie hier eine funktionierende Demo. Es wird zwischen meinen drei Lieblingsbüchern in meinen drei Lieblingsprogrammiersprachen wechseln. Die URL für jedes Buch ist jedes Mal einzigartig, sodass Sie die Vorschau sehen können. Sie möchten jedoch wahrscheinlich die Dinge in Ihrem Devtools -Netzwerk -Registerkarte drosseln, um die Dinge wirklich zu sehen.

Ganze Code anzeigen
 Klassenbuchcover erweitert Htmlelement {
  static beobachteteAttributes = ['url'];

  AttributEchangedCallback (Name, OldValue, NewValue) {
    if (name === 'url') {
      this.createmainimage (NewValue);
    }
  }

  Setzen Sie Vorschau (Val) {
    this.previewel = this.CreatePreview (Val);
    this.render ();
  }

  CreatePreview (Val) {
    if (typeof val === 'String') {
      return base64Preview (Val);
    } anders {
      return BlurhashPreview (Val);
    }
  }

  CreateMainimage (URL) {
    this.loaded = false;
    const img = document.createelement ('img');
    img.alt = 'Buchcover';
    img.addeventListener ('last', () = & gt; {{
      if (img === this.imageel) {
        this.loaded = true;
        this.render ();
      }
    });
    img.src = url;
    this.imageel = img;
  }

  connectedCallback () {
    this.render ();
  }

  render () {
    const elementmaybe = this.load? this.imageel: this.previewel;
    syncsinglechild (this, elementmaybe);
  }
}
Nach dem Login kopieren

Zunächst registrieren wir das Attribut, an dem wir interessiert sind, und reagieren, wenn es sich ändert:

 static beobachteteAttributes = ['url'];

AttributEchangedCallback (Name, OldValue, NewValue) {
  if (name === 'url') {
    this.createmainimage (NewValue);
  }
}
Nach dem Login kopieren

Dies führt dazu, dass unsere Bildkomponente erstellt wird, was nur dann angezeigt wird, wenn sie geladen werden:

 CreateMainimage (URL) {
  this.loaded = false;
  const img = document.createelement ('img');
  img.alt = 'Buchcover';
  img.addeventListener ('last', () => {
    if (img === this.imageel) {
      this.loaded = true;
      this.render ();
    }
  });
  img.src = url;
  this.imageel = img;
}
Nach dem Login kopieren

Als nächstes haben wir unsere Vorschau -Eigenschaft, die entweder unsere Base64 -Vorschau -Zeichenfolge oder unser Blurhash -Paket sein kann:

 Setzen Sie Vorschau (Val) {
  this.previewel = this.CreatePreview (Val);
  this.render ();
}

CreatePreview (Val) {
  if (typeof val === 'String') {
    return base64Preview (Val);
  } anders {
    return BlurhashPreview (Val);
  }
}
Nach dem Login kopieren

Dies ist auf diejenigen Helferfunktion, die wir brauchen:

 Funktion Base64Preview (Val) {
  const img = document.createelement ('img');
  img.src = val;
  zurück img;
}

Funktion BlurhashPreview (Vorschau) {
  const canvasel = document.createelement ('canvas');
  const {W: Breite, H: Höhe} = Vorschau;

  canvasel.width = width;
  Canvasel.Height = Höhe;

  const pixels = decode (Vorschau.BLURHASH, Breite, Höhe);
  const ctx = canvasel.getContext ('2d');
  Constant imagedata = ctx.createimagedata (Breite, Höhe);
  Imagedata.Data.set (Pixel);
  ctx.putimagedata (Imagedata, 0, 0);

  Leinwand zurückgeben;
}
Nach dem Login kopieren

Und schließlich unsere Render -Methode:

 connectedCallback () {
  this.render ();
}

render () {
  const elementmaybe = this.load? this.imageel: this.previewel;
  syncsinglechild (this, elementmaybe);
}
Nach dem Login kopieren

Und ein paar Helfermethoden, um alles zusammenzubinden:

 Exportfunktion SyncSingLechild (Container, Kind) {
  const CurrentChild = Container.FirstelementChild;
  if (currentChild! == child) {
    ClearContainer (Container);
    if (Kind) {
      Container.AppendChild (Kind);
    }
  }
}

Exportfunktion ClearContainer (el) {
  Kind lassen;

  while ((child = el.firstelementChild)) {
    El.Removechild (Kind);
  }
}
Nach dem Login kopieren

Es ist ein bisschen mehr Kesselplatte als wir brauchen würden, wenn wir dies in einem Framework erstellen, aber der Vorteil ist, dass wir dies in jedem Framework wiederverwenden können-obwohl React vorerst einen Wrapper benötigt, wie wir besprochen haben.

Krimskrams

Ich habe Lits React Wrapper bereits erwähnt. Wenn Sie jedoch die Schablone verwenden, unterstützt sie tatsächlich eine separate Ausgangspipeline nur für React. Und die guten Leute von Microsoft haben auch etwas Ähnliches wie Lits Wrapper erstellt, das an die Fast -Web -Komponenten -Bibliothek angeschlossen ist.

Wie ich bereits erwähnt habe, werden alle Frameworks, die nicht mit React benannt sind, die Einstellungs -Webkomponenteneigenschaften für Sie verarbeiten. Beachten Sie nur, dass einige einige besondere Aromen von Syntax haben. Beispielsweise nimmt beispielsweise mit Solid.js immer an, dass Wert eine Eigenschaft ist, die Sie mit einem Attr-Präfix wie überschreiben können.

Einpacken

Webkomponenten sind ein interessanter, oft nicht genutzter Bestandteil der Webentwicklungslandschaft. Sie können dazu beitragen, Ihre Abhängigkeit von einem einzelnen JavaScript -Framework durch Verwaltung Ihrer Benutzeroberfläche oder „Blatt“ -Komponenten zu verringern. Während das Erstellen dieser als Webkomponenten - im Gegensatz zu Svelte- oder React -Komponenten - nicht so ergonomisch ist, ist der Vorteil, dass sie weithin wiederverwendbar sind.

Das obige ist der detaillierte Inhalt vonAufbau interoperabler Webkomponenten, die funktionieren. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage