Eine Anleitung, um Benutzerdefinierte Elemente für Entwickler Reagieren

0
9

Ich hatte zum Aufbau einer UI und vor kurzem (zum ersten mal in einer langen Weile) habe ich nicht die option React.js,, das ist meine bevorzugte Lösung für die UI in diesen Tagen. So, schaute ich, was das built-in-browser-APIs zu bieten hatte, und sah, dass die Verwendung von benutzerdefinierten Elementen (aka Web-Komponenten) kann nur sein, das zu beheben, diese Reagieren Entwickler benötigt.

Benutzerdefinierte Elemente können bieten die gleichen Allgemeinen Vorteile des React-Komponenten, ohne an einen bestimmten framework-Implementierung. Ein benutzerdefiniertes element gibt uns ein neues HTML-tag, wir können programmgesteuert über eine native browser-API.

Reden wir über die Vorteile von component-based UI:

  • Kapselung – Anliegen bezieht sich auf die Komponente bleibt in dieser Komponente ist die Implementierung
  • Wiederverwendbarkeit – wenn die Benutzeroberfläche ist aufgeteilt in mehrere generische Stücke, Sie sind leichter zu brechen in mustern, die Sie sind wahrscheinlicher, Sie zu wiederholen
  • Isolation – da-Komponenten sind so konzipiert, gekapselt und mit, dass Sie den zusätzlichen Vorteil, die Isolierung, die es Ihnen ermöglicht Bereich bugs und änderungen an einem bestimmten Teil der Anwendung einfacher

Anwendungsfälle

Sie werden sich vielleicht Fragen, wer ist mit benutzerdefinierte Elemente in die Produktion. Insbesondere:

  • GitHub ist mit benutzerdefinierte Elemente für Ihre modale Dialoge”, “AutoVervollständigen” und Anzeige der Zeit.
  • YouTube-die neue web-app wurde mit Polymer-und web-Komponenten.

Ähnlichkeiten an die Komponente-API

Wenn Sie versuchen, zu vergleichen, Reagieren die Komponenten versus benutzerdefinierte Elemente, ich fand die APIs wirklich ähnlich:

  • Sie sind beide Klassen, die nicht die “neuen” und sind in der Lage, erweitern Sie eine Basis-Klasse
  • Sie beide Erben ein Montage-oder rendering-lifecycle
  • Sie nehmen sowohl statische oder dynamische Eingabe über Requisiten oder Attribute

Demo

Also, lasst uns bauen eine kleine Anwendung, die Listen details über ein GitHub-repository.

Wenn ich im Begriff waren, diesen Ansatz mit zu Reagieren, würde ich definieren, eine einfache Komponente wie folgt:

<Repository name=”charliewilco/obsidian” />

Diese Komponente ist ein einzelner prop — den Namen des repository — und wir setzen es so:

Klasse Repository erweitert Reagieren.Komponente {
state = {
repo: null
};

async getDetails(name) {
Rückkehr erwarten fetch(`https://api.github.com/repos/${name}`, {
Modus: ‘cors’
}).dann(res => res.json());
}

async componentDidMount() {
const { name } =.Requisiten;
const repo = erwarten.getDetails(name);
diese.setState({ repo });
}

render() {
const { repo -} =.Zustand;

if (!repo) {
zurück <h1>Loading</h1>;
}

wenn (repo.Nachricht) {
Rückkehr <div className=”Karte-Karte–error”>Fehler: {repo.message}</div>;
}

return (
<div class=”Karte”>
<beiseite>
<img
width=”48″
height=”48″
class=”Avatar”
src={repo.Besitzer.avatar_url}
alt=”Profilbild für ${repo.Besitzer.login}”
/>
</aside>
<header>
<h2 class=”Karte__title”>{repo.full_name}</h2>
<span class=”Card – __ – meta”>{repo.Beschreibung}</span>
</header>
</div>
);
}
}

Finden Sie den Stift Reagieren Demo – GitHub von Charles (@charliewilco) auf CodePen.

Brechen diese weiter nach unten, wir haben eine Komponente, hat Ihren eigenen Staat, das ist der repo-details. Zunächst setzen wir Sie auf null sein, da haben wir keine Daten noch, so haben wir die laden-Anzeige, während die Daten abgeholt werden.

Während die Reagieren Lebenszyklus verwenden wir Holen, Holen Sie die Daten von GitHub, legen Sie die Karte, und lösen eine re-Rendern mit setState() nachdem wir Holen die Daten zurück. Alle diese verschiedenen Zustände der UI nimmt, sind vertreten in der render () – Methode.

Definieren / Verwenden ein Benutzerdefiniertes Element

Sie tun dies mit benutzerdefinierten Elementen ist ein wenig anders. Wie Reagieren die Komponente, unser custom-element ein Attribut — immer wieder, der name der repository — und verwalten Sie Ihren eigenen Staat.

Unser element wird wie folgt Aussehen:

<github-repo name=”charliewilco/obsidian”></github-repo>
<github-repo name=”charliewilco/Ebene.css”></github-repo>
<github-repo name=”charliewilco/reagieren-Zweige”></github-repo>
<github-repo name=”charliewilco/reagieren-gluejar”></github-repo>
<github-repo name=”charliewilco/dotfiles”></github-repo>

Finden Sie den Stift Benutzerdefinierte Elemente Demo – GitHub von Charles (@charliewilco) auf CodePen.

Um zu beginnen, alles, was wir tun müssen, um zu definieren und registrieren Sie ein benutzerdefiniertes element ist, erstellen Sie eine Klasse, die Sie erweitert die HTMLElement-Klasse und registrieren Sie den Namen des Elements mit customElements.define().

Klasse OurCustomElement erstreckt HTMLElement {}
Fenster.customElements.define(‘unsere-element”, OurCustomElement);

Und wir nennen es:

<unsere-element></unser-element>

Dieses neue element ist nicht sehr nützlich, aber mit custom-Elementen, wir bekommen drei Methoden zum erweitern der Funktionalität dieses Elements. Diese sind fast Analog zu Reagieren lifecycle-Methoden für eine Komponente API. Die beiden lifecycle-Methoden wie die meisten für uns relevanten sind die disconnectedCallBack und die connectedCallback und da ist eine Klasse, es kommt mit einem Konstruktor.

Name
Wird aufgerufen, wenn

Konstruktor Eine Instanz des Elements erstellt oder aktualisiert. Nützlich für den Status “Initialisierung”, “Einstellungen”, bis die Ereignis-Listener, oder das erstellen von Shadow-DOM. Siehe die Skillung für Einschränkungen auf, was Sie tun können, in den Konstruktor.
connectedCallback Das element ist eingefügt in die DOM. Nützlich zum ausführen von setup-code, wie das abrufen von Ressourcen oder Rendern von UI. Im Allgemeinen sollten Sie versuchen, zu verzögern, die Arbeit bis zu diesem Zeitpunkt
disconnectedCallback Wenn das element aus dem DOM entfernt. Nützlich für das ausführen clean-up-code.

Für die Umsetzung unserer benutzerdefiniertes element erstellen wir die Klasse und setzen einige Attribute im Zusammenhang mit, dass UI:

Klasse Repository erweitert HTMLElement {
Konstruktor() {
super();

diese.repoDetails = null;

diese.name = diese.getAttribute(“name”);
diese.endpoint = `https://api.github.com/repos/${dies.name}`
diese.innerHTML = `<h1>Loading</h1>`
}
}

Durch Aufruf von super() im Konstruktor den Kontext dieses ist das element selbst, und die DOM-manipulation APIs verwendet werden können. Bisher haben wir das Standard-repository-details auf null gesetzt wird, bekommen die repo-name aus dem element-Attribut, erstellt einen Endpunkt zu nennen, so haben wir nicht zu definieren, es später und, am wichtigsten ist, stellen Sie die ursprüngliche HTML eine Ladeanzeige.

Um die details zu diesem element repository, wir gehen zu müssen, um eine Anfrage an GitHub API. Wir verwenden die fetch-und-da das Versprechen-basiert, benutzen wir Sie async und await, um unseren code besser lesbar. Sie können lernen, mehr über das async/await-Schlüsselwörter hier und mehr über die browser-fetch API hier. Sie können auch tweet bei mir, um herauszufinden, ob ich es lieber zu den Axios-Bibliothek. (Tipp, es hängt davon ab, ob ich Tee oder Kaffee mit meinem Frühstück.)

Nun fügen wir eine Methode, um diese Klasse zu Fragen, GitHub für details über das repository.

Klasse Repository erweitert HTMLElement {
Konstruktor() {
// …
}

async getDetails() {
Rückkehr erwarten fetch(dies.Endpunkt, { Modus: “cors” }).dann(res => res.json());
}
}

Als Nächstes verwenden wir die connectedCallback Methode und der Shadow DOM mit der return-Wert dieser Methode. Mit dieser Methode wird etwas ähnliches tun, wie wenn wir genannt Repository.componentDidMount() Reagieren Beispiel. Anstatt, wir überschreiben den Wert null haben wir anfangs gab.repoDetails — wir werden dieses dann später, wenn wir beginnen, rufen Sie die Vorlage zum erstellen des HTML-Codes.

Klasse Repository erweitert HTMLElement {
Konstruktor() {
// …
}

async getDetails() {
// …
}

async connectedCallback() {
lassen Sie repo = erwarten.getDetails();
diese.repoDetails = repo;
diese.initShadowDOM();
}

initShadowDOM() {
lassen Sie shadowRoot =.attachShadow({ mode: “open” });
shadowRoot.innerHTML = this.Vorlage;
}
}

Sie werden bemerken, dass wir den Aufruf von Methoden im Zusammenhang mit der Shadow DOM. Abgesehen davon, dass ein abgelehnter Titel für einen Marvel-Film, der Shadow DOM hat seine eigene umfangreiche API, lohnt ein Blick in. Für unsere Zwecke, obwohl, es wird Abstrakt der Implementierung von innerHTML hinzufügen, um das element.

Jetzt sind wir die Zuordnung der innerHTML-gleich dem Wert dieser.- Vorlage. Wir definieren nun:

Klasse Repository erweitert HTMLElement {
Vorlage Holen() {
const repo =.repoDetails;

// wenn wir eine Fehlermeldung bekommen, lassen Sie uns zeigen, dass die zurück an den Benutzer
wenn (repo.Nachricht) {
return `<div class=”Card-Karte–error”>Fehler: ${repo.message}</div>`
} else {
return `
<div class=”Karte”>
<beiseite>
<img width=”48″ height=”48″ class=”Avatar” src=”${repo.Besitzer.avatar_url}” alt=”Profilbild für ${repo.Besitzer.login}” />
</aside>
<header>
<h2 class=”Karte__title”>${repo.full_name}</h2>
<span class=”Card – __ – meta”>${repo.Beschreibung}</span>
</header>
</div>
`
}
}
}

Das ist ziemlich viel es. Wir haben definiert ein benutzerdefiniertes element, das verwaltet seine eigenen Staat, holt seinen eigenen Daten und spiegelt wider, dass Staat zurück an den Benutzer, wenn wir uns ein HTML-element verwenden in unserer Anwendung.

Nachdem man durch diese übung, ich fand, dass die einzige erforderliche Abhängigkeit für benutzerdefinierte Elemente wird die browser die nativen APIs eher als einen Rahmen, um zusätzlich zu analysieren und auszuführen. Dies sorgt für eine tragbare und wiederverwendbare Lösung mit ähnlichen APIs der frameworks, die Sie bereits lieben und verwenden, um Ihr Leben.

Gibt es Nachteile bei dieser Vorgehensweise natürlich. Wir reden über verschiedene browser-support-Fragen und einige Mangel an Konsistenz. Plus, arbeiten mit DOM-manipulation APIs können sehr verwirrend sein. Manchmal sind Sie Zuordnungen. Manchmal sind Sie Funktionen. Manchmal sind diese Funktionen nehmen einen Rückruf und manchmal nicht. Wenn Sie mir nicht glauben, werfen Sie einen Blick auf das hinzufügen einer Klasse zu einem HTML-element über document.createElement(), die fünf top-Gründe, um zu Reagieren. Die grundlegende Implementierung ist nicht kompliziert, aber es ist unvereinbar mit anderen ähnlichen Dokument-Methoden.

Die eigentliche Frage ist: ist es noch in der Wäsche? Vielleicht. Reagieren ist immer noch ziemlich gut an die Dinge, die es ist entworfen, um sehr sehr gut an: der virtuelle DOM, die Verwaltung, den Zustand der Anwendung, Kapselung und Weitergabe der Daten den Baum hinunter. Es gibt neben kein Anreiz zur Verwendung von benutzerdefinierten Elementen innerhalb dieses Rahmens. Benutzerdefinierte Elemente, auf der anderen Seite, sind einfach vorhanden, die aufgrund der Erstellung einer Anwendung für den browser.

Erfahren Sie mehr

  • Benutzerdefinierte Elemente v1: Wiederverwendbare Web-Komponenten
  • Eine Native Web-Komponenten mit Benutzerdefinierten Elementen v1 und Shadow DOM v1

Das Jetpack WordPress-plugin läuft auf dieser Website, indem Sie nicht nur die verwandten Beiträge unten, aber die social sharing links oben, der Sicherheit und des backups, Markdown-support, site-Suche, das Kommentar-Formular, postulieren soziale Netzwerk-verbindungen und vieles mehr!