So funktioniert JS: Benutzerdefinierte Elemente


Wir präsentieren Ihnen eine Übersetzung von 19 Artikeln aus der SessionStack- Materialreihe zu den Merkmalen verschiedener Mechanismen des JavaScript-Ökosystems. Heute werden wir über den Standard für benutzerdefinierte Elemente sprechen - die sogenannten "benutzerdefinierten Elemente". Wir werden darüber sprechen, welche Aufgaben sie lösen dürfen und wie sie erstellt und verwendet werden.

Bild


Rückblick


In einem der vorherigen Artikel dieser Reihe haben wir über das Shadow DOM und einige andere Technologien gesprochen, die Teil eines größeren Phänomens sind - Webkomponenten. Webkomponenten sollen Entwicklern ermöglichen, die Standardfunktionen von HTML zu erweitern, indem sie kompakte, modulare und wiederverwendbare Elemente erstellen. Dies ist der relativ neue W3C-Standard, den Hersteller aller führenden Browser bereits bemerkt haben. Er ist in der Produktion zu finden, obwohl seine Arbeit natürlich von Polyphilen stammt (wir werden später darüber sprechen).

Wie Sie vielleicht bereits wissen, bieten uns Browser einige wichtige Tools für die Entwicklung von Websites und Webanwendungen. Es geht um HTML, CSS und JavaScript. HTML wird verwendet, um Webseiten zu strukturieren. Dank CSS erhalten sie ein schönes Aussehen, und JavaScript ist für die interaktiven Funktionen verantwortlich. Vor dem Erscheinen von Webkomponenten war es jedoch nicht so einfach, von JavaScript implementierte Aktionen einer HTML-Struktur zuzuordnen.

In der Tat werden wir hier die Basis von Webkomponenten betrachten - benutzerdefinierte Elemente. Kurz gesagt, die API, die für die Zusammenarbeit mit ihnen entwickelt wurde, ermöglicht es dem Programmierer, eigene HTML-Elemente mit integrierter JavaScript-Logik und von CSS beschriebenen Stilen zu erstellen. Viele verwechseln benutzerdefinierte Elemente mit der Shadow DOM-Technologie. Dies sind jedoch zwei völlig unterschiedliche Dinge, die sich zwar ergänzen, aber nicht austauschbar sind.

Einige Frameworks (wie Angular oder React) versuchen, dasselbe Problem zu lösen, das benutzerdefinierte Elemente lösen, indem sie ihre eigenen Konzepte einführen. Benutzerdefinierte Elemente können mit Angular-Direktiven oder mit React-Komponenten verglichen werden. Benutzerdefinierte Elemente sind jedoch eine Standardfunktion des Browsers. Sie müssen nur gewöhnliches JavaScript, HTML und CSS verwenden, um mit ihnen zu arbeiten. Dies erlaubt uns natürlich nicht zu sagen, dass sie ein Ersatz für gewöhnliche JS-Frameworks sind. Moderne Frameworks bieten uns viel mehr als nur die Möglichkeit, das Verhalten benutzerdefinierter Elemente zu simulieren. Infolgedessen können wir sagen, dass sowohl Frameworks als auch Benutzerelemente Technologien sind, die zusammen zur Lösung von Webentwicklungsaufgaben verwendet werden können.

API


Bevor wir fortfahren, wollen wir uns ansehen, welche Möglichkeiten uns die API bietet, mit benutzerdefinierten Elementen zu arbeiten. Es handelt sich nämlich um ein globales customElements Objekt mit mehreren Methoden:

  • Mit der Methode define(tagName, constructor, options) können Sie ein neues Benutzerelement definieren (erstellen, registrieren). Es werden drei Argumente benötigt - der Tag-Name für das Benutzerelement, der den Namensregeln für solche Elemente entspricht, eine Klassendeklaration und ein Objekt mit Parametern. Derzeit wird nur ein Parameter unterstützt - extends . Hierbei handelt es sich um eine Zeichenfolge, die den Namen des zu erweiternden Inline-Elements angibt. Mit dieser Funktion werden spezielle Versionen von Standardelementen erstellt.
  • Die Methode get(tagName) gibt den Konstruktor des Benutzerelements zurück, sofern dieses Element bereits definiert ist, andernfalls wird undefined . Es braucht ein Argument - das Namensschild des Benutzerelements.
  • Die whenDefined(tagName) -Methode gibt das Versprechen zurück, das nach dem whenDefined(tagName) des Benutzerelements aufgelöst wird. Wenn ein Element bereits definiert ist, wird dieses Versprechen sofort gelöst. Ein Versprechen wird abgelehnt, wenn der übergebene Tag-Name kein gültiger Tag-Name für das Benutzerelement ist. Diese Methode akzeptiert den Tag-Namen des Benutzerelements.

Erstellen Sie benutzerdefinierte Elemente


Das Erstellen benutzerdefinierter Elemente ist sehr einfach. Dazu müssen zwei Dinge getan werden: Erstellen Sie eine Klassendeklaration für das Element, das die HTMLElement Klasse erweitern soll, und registrieren Sie dieses Element unter dem ausgewählten Namen. So sieht es aus:

 class MyCustomElement extends HTMLElement { constructor() {   super();   // … } // … } customElements.define('my-custom-element', MyCustomElement); 

Wenn Sie den aktuellen Bereich nicht verschmutzen möchten, können Sie eine anonyme Klasse verwenden:

 customElements.define('my-custom-element', class extends HTMLElement { constructor() {   super();   // … } // … }); 

Wie Sie den Beispielen customElements.define(...) können, wird das Benutzerelement mit der customElements.define(...) bereits bekannten Methode customElements.define(...) registriert.

Probleme, die benutzerdefinierte Elemente lösen


Lassen Sie uns über die Probleme sprechen, mit denen wir benutzerdefinierte Elemente lösen können. Eine davon besteht darin, die Struktur des Codes zu verbessern und die sogenannte Div-Tag-Suppe (Div-Suppe) zu eliminieren. Dieses Phänomen ist eine sehr häufige Codestruktur in modernen Webanwendungen, in denen viele div Elemente ineinander eingebettet sind. So könnte es aussehen:

 <div class="top-container"> <div class="middle-container">   <div class="inside-container">     <div class="inside-inside-container">       <div class="are-we-really-doing-this">         <div class="mariana-trench">           …         </div>       </div>     </div>   </div> </div> </div> 

Ein solcher HTML-Code wird aus berechtigten Gründen verwendet - er beschreibt das Layout der Seite und stellt die korrekte Anzeige auf dem Bildschirm sicher. Dies beeinträchtigt jedoch die Lesbarkeit des HTML-Codes und erschwert dessen Wartung.

Angenommen, wir haben eine Komponente, die wie in der folgenden Abbildung aussieht.


Erscheinungsbild der Komponenten

Unter Verwendung des traditionellen Ansatzes zur Beschreibung solcher Dinge entspricht der folgende Code dieser Komponente:

 <div class="primary-toolbar toolbar"> <div class="toolbar">   <div class="toolbar-button">     <div class="toolbar-button-outer-box">       <div class="toolbar-button-inner-box">         <div class="icon">           <div class="icon-undo"> </div>         </div>       </div>     </div>   </div>   <div class="toolbar-button">     <div class="toolbar-button-outer-box">       <div class="toolbar-button-inner-box">         <div class="icon">           <div class="icon-redo"> </div>         </div>       </div>     </div>   </div>   <div class="toolbar-button">     <div class="toolbar-button-outer-box">       <div class="toolbar-button-inner-box">         <div class="icon">           <div class="icon-print"> </div>         </div>       </div>     </div>   </div>   <div class="toolbar-toggle-button toolbar-button">     <div class="toolbar-button-outer-box">       <div class="toolbar-button-inner-box">         <div class="icon">           <div class="icon-paint-format"> </div>         </div>       </div>     </div>   </div> </div> </div> 

Stellen Sie sich nun vor, wir könnten anstelle dieses Codes diese Beschreibung der Komponente verwenden:

 <primary-toolbar> <toolbar-group>   <toolbar-button class="icon-undo"></toolbar-button>   <toolbar-button class="icon-redo"></toolbar-button>   <toolbar-button class="icon-print"></toolbar-button>   <toolbar-toggle-button class="icon-paint-format"></toolbar-toggle-button> </toolbar-group> </primary-toolbar> 

Ich bin sicher, jeder wird zustimmen, dass das zweite Codefragment viel besser aussieht. Dieser Code ist leichter zu lesen, leichter zu warten und sowohl für den Entwickler als auch für den Browser verständlich. Es kommt alles auf die Tatsache an, dass es einfacher ist als das, in dem es viele verschachtelte div Tags gibt.

Das nächste Problem, das mit benutzerdefinierten Elementen gelöst werden kann, ist die Wiederverwendung von Code. Der Code, den Entwickler schreiben, sollte nicht nur funktionieren, sondern auch unterstützt werden. Die Wiederverwendung von Code im Gegensatz zum ständigen Schreiben derselben Konstrukte verbessert die Projektunterstützungsfunktionen.
Hier ist ein einfaches Beispiel, das Ihnen hilft, diese Idee besser zu verstehen. Angenommen, wir haben das folgende Element:

 <div class="my-custom-element"> <input type="text" class="email" /> <button class="submit"></button> </div> 

Wenn Sie es ständig brauchen, müssen wir mit dem üblichen Ansatz immer wieder denselben HTML-Code schreiben. Stellen Sie sich nun vor, Sie müssen eine Änderung an diesem Code vornehmen, die überall dort angezeigt werden soll, wo sie verwendet wird. Dies bedeutet, dass wir alle Stellen finden müssen, an denen dieses Fragment verwendet wird, und dann überall dieselben Änderungen vornehmen müssen. Es ist lang, hart und voller Fehler.

Es wäre viel besser, wenn wir könnten, wo dieses Element benötigt wird, schreiben Sie einfach Folgendes:

 <my-custom-element></my-custom-element> 

Moderne Webanwendungen sind jedoch viel mehr als statisches HTML. Sie sind interaktiv. Die Quelle ihrer Interaktivität ist JavaScript. Um solche Funktionen bereitzustellen, werden normalerweise einige Elemente erstellt und anschließend Ereignis-Listener mit ihnen verbunden, sodass sie auf Benutzereinflüsse reagieren können. Sie können beispielsweise auf Klicks reagieren, auf das „Bewegen“ des Mauszeigers über sie, auf das Ziehen über den Bildschirm usw. So verbinden Sie einen Ereignis-Listener mit einem Element, das auftritt, wenn Sie mit der Maus darauf klicken:

 var myDiv = document.querySelector('.my-custom-element'); myDiv.addEventListener('click', _ => { myDiv.innerHTML = '<b> I have been clicked </b>'; }); 

Und hier ist der HTML-Code für dieses Element:

 <div class="my-custom-element"> I have not been clicked yet. </div> 

Durch die Verwendung der API für die Arbeit mit benutzerdefinierten Elementen kann all diese Logik in das Element selbst aufgenommen werden. Zum Vergleich - unten finden Sie den Code zum Deklarieren eines benutzerdefinierten Elements, das einen Ereignishandler enthält:

 class MyCustomElement extends HTMLElement { constructor() {   super();   var self = this;   self.addEventListener('click', _ => {     self.innerHTML = '<b> I have been clicked </b>';   }); } } customElements.define('my-custom-element', MyCustomElement); 

Und so sieht es im HTML-Code der Seite aus:

 <my-custom-element> I have not been clicked yet </my-custom-element> 

Auf den ersten Blick scheint es, dass mehr Zeilen JS-Code erforderlich sind, um ein benutzerdefiniertes Element zu erstellen. In realen Anwendungen kommt es jedoch selten vor, dass solche Elemente nur zur einmaligen Verwendung erstellt werden. Ein weiteres typisches Phänomen in modernen Webanwendungen besteht darin, dass die meisten Elemente in ihnen dynamisch erstellt werden. Dies führt dazu, dass zwei verschiedene Szenarien für die Arbeit mit Elementen unterstützt werden müssen - Situationen, in denen sie mithilfe von JavaScript dynamisch zur Seite hinzugefügt werden, und Situationen, in denen sie in der ursprünglichen HTML-Struktur der Seite beschrieben werden. Dank der Verwendung benutzerdefinierter Elemente wird die Arbeit in diesen beiden Situationen vereinfacht.

Wenn wir die Ergebnisse dieses Abschnitts zusammenfassen, können wir daher sagen, dass Benutzerelemente den Code klarer machen, seine Unterstützung vereinfachen und ihn in kleine Module aufteilen, die alle erforderlichen Funktionen enthalten und für die Wiederverwendung geeignet sind.

Nachdem wir die allgemeinen Probleme beim Arbeiten mit benutzerdefinierten Elementen besprochen haben, wollen wir uns mit deren Funktionen befassen.

Anforderungen


Bevor Sie mit der Entwicklung eigener benutzerdefinierter Elemente beginnen, sollten Sie einige der Regeln kennen, die Sie beim Erstellen befolgen müssen. Hier sind sie:

  • Der Komponentenname muss einen Bindestrich ( - Symbol) enthalten. Dank dessen kann der HTML-Parser zwischen eingebetteten und Benutzerelementen unterscheiden. Darüber hinaus stellt dieser Ansatz sicher, dass keine Kollisionen von Namen mit integrierten Elementen auftreten (sowohl mit denen, die jetzt sind, als auch mit denen, die in Zukunft erscheinen werden). Der tatsächliche Name des benutzerdefinierten Elements lautet beispielsweise >my-custom-element< , und die Namen >myCustomElement< und <my_custom_element> sind nicht geeignet.
  • Es ist verboten, dasselbe Tag mehrmals zu registrieren. Wenn Sie dies versuchen, gibt der Browser DOMException Fehler aus. Benutzerdefinierte Elemente können nicht neu definiert werden.
  • Benutzerdefinierte Tags können sich nicht selbst schließen. Der HTML-Parser unterstützt nur eine begrenzte Anzahl von selbstschließenden Standard-Tags (z. B. <img> , <link> , <br> ).

Die Möglichkeiten


Lassen Sie uns darüber sprechen, was Sie mit benutzerdefinierten Elementen tun können. Wenn Sie diese Frage auf den Punkt bringen, stellt sich heraus, dass Sie mit ihnen viele interessante Dinge tun können.

Eine der bemerkenswertesten Eigenschaften von benutzerdefinierten Elementen ist, dass sich die Deklaration einer Elementklasse auf das DOM-Element selbst bezieht. Dies bedeutet, dass Sie das Schlüsselwort this in einer Anzeige verwenden können, um Ereignis-Listener zu verbinden, auf Eigenschaften zuzugreifen, untergeordnete Knoten zu erstellen usw.

 class MyCustomElement extends HTMLElement { // ... constructor() {   super();   this.addEventListener('mouseover', _ => {     console.log('I have been hovered');   }); } // ... } 

Dies ermöglicht es natürlich, neue Daten in die untergeordneten Knoten des Elements zu schreiben. Dies wird jedoch nicht empfohlen, da dies zu unerwartetem Verhalten der Elemente führen kann. Wenn Sie sich vorstellen, dass Sie Elemente verwenden, die von einer anderen Person entworfen wurden, werden Sie wahrscheinlich überrascht sein, wenn Ihr eigenes Markup im Element durch etwas anderes ersetzt wird.

Es gibt verschiedene Methoden, mit denen Sie Code an bestimmten Punkten im Lebenszyklus eines Elements ausführen können.

  • Die constructor wird einmal aufgerufen, wenn das Element erstellt oder "aktualisiert" wird (wir werden weiter unten darauf eingehen). Am häufigsten wird es verwendet, um den Status eines Elements zu initialisieren, Ereignis-Listener zu verbinden, ein Schatten-DOM zu erstellen usw. Vergessen Sie nicht, dass Sie im Konstruktor immer super() aufrufen müssen.
  • Die connectedCallback Methode wird jedes Mal aufgerufen, wenn ein Element zum DOM hinzugefügt wird. Es kann verwendet werden (und genau so wird es empfohlen), um die Ausführung von Aktionen auf den Moment zu verschieben, in dem das Element auf der Seite angezeigt wird (auf diese Weise können Sie beispielsweise das Laden einiger Daten verzögern).
  • Die Methode " disconnectedCallback "wird aufgerufen, wenn ein Element aus dem DOM entfernt wird. Es wird normalerweise verwendet, um Ressourcen freizugeben. Beachten Sie, dass diese Methode nicht aufgerufen wird, wenn der Benutzer die Browser-Registerkarte mit der Seite schließt. Verlassen Sie sich daher nicht auf ihn, wenn dies erforderlich ist, um einige besonders wichtige Aktionen auszuführen.
  • Die attributeChangedCallback Methode wird aufgerufen, wenn ein Elementattribut hinzugefügt, entfernt, aktualisiert oder ersetzt wird. Außerdem wird es aufgerufen, wenn das Element vom Parser erstellt wird. Beachten Sie jedoch, dass diese Methode nur für Attribute gilt, die in der Eigenschaft ObservedAttributes aufgeführt sind.
  • Die adoptedCallback Methode adoptedCallback aufgerufen, wenn die document.adoptNode(...) -Methode verwendet wird, mit der der Knoten in ein anderes Dokument verschoben wird.

Bitte beachten Sie, dass alle oben genannten Methoden synchron sind. Beispielsweise wird die Methode linkedCallback unmittelbar nach dem Hinzufügen des Elements zum DOM aufgerufen, und der Rest des Programms wartet auf den Abschluss dieser Methode.

Eigenschaftsreflexion


Eingebettete HTML-Elemente haben eine sehr praktische Funktion: die Eigenschaftsreflexion. Dank dieses Mechanismus werden die Werte einiger Eigenschaften direkt als Attribute im DOM wiedergegeben. Angenommen, dies ist charakteristisch für die id Eigenschaft. Zum Beispiel führen wir die folgende Operation aus:

 myDiv.id = 'new-id'; 

Relevante Änderungen wirken sich auf das DOM aus:

 <div id="new-id"> ... </div> 

Dieser Mechanismus arbeitet in die entgegengesetzte Richtung. Dies ist sehr nützlich, da Sie damit Elemente deklarativ konfigurieren können.

Benutzerdefinierte Elemente verfügen nicht über diese integrierte Funktion, Sie können sie jedoch selbst implementieren. Damit sich einige Eigenschaften von Benutzerelementen ähnlich verhalten, können Sie deren Getter und Setter konfigurieren.

 class MyCustomElement extends HTMLElement { // ... get myProperty() {   return this.hasAttribute('my-property'); } set myProperty(newValue) {   if (newValue) {     this.setAttribute('my-property', newValue);   } else {     this.removeAttribute('my-property');   } } // ... } 

Vorhandene Elemente erweitern


Mit der API für benutzerdefinierte Elemente können Sie nicht nur neue HTML-Elemente erstellen, sondern auch vorhandene erweitern. Darüber hinaus sprechen wir sowohl über Standardelemente als auch über benutzerdefinierte. Dies erfolgt mithilfe des extends wenn eine Klasse deklariert wird:

 class MyAwesomeButton extends MyButton { // ... } customElements.define('my-awesome-button', MyAwesomeButton);</cosourcede>      ,  , ,    <code>customElements.define(...)</code>,    <code>extends</code>   ,      .     ,        ,        DOM-.   ,          ,      ,       . <source>class MyButton extends HTMLButtonElement { // ... } customElements.define('my-button', MyButton, {extends: 'button'}); 

Erweiterte Standardelemente werden auch als "benutzerdefinierte integrierte Elemente" bezeichnet.

Es wird empfohlen, es zur Regel zu machen, vorhandene Elemente immer zu erweitern und schrittweise durchzuführen. Auf diese Weise können Sie in neuen Elementen die Funktionen speichern, die in zuvor erstellten Elementen implementiert wurden (dh Eigenschaften, Attribute, Funktionen).

Bitte beachten Sie, dass benutzerdefinierte integrierte Elemente jetzt nur in Chrome 67+ unterstützt werden. Dies wird in anderen Browsern angezeigt. Es ist jedoch bekannt, dass Safari-Entwickler beschlossen haben, diese Möglichkeit nicht zu implementieren.

Elemente aktualisieren


Wie bereits erwähnt, werden mit der Methode customElements.define(...) benutzerdefinierte Elemente registriert. Die Registrierung kann jedoch nicht als die Aktion bezeichnet werden, die zuerst ausgeführt werden muss. Die Registrierung von Benutzerelementen kann für eine Weile verschoben werden. Darüber hinaus kann diese Zeit auch dann eintreten, wenn das Element bereits zum DOM hinzugefügt wurde. Dieser Vorgang wird als Upgrade bezeichnet. Um herauszufinden, wann ein Element registriert wird, stellt der Browser die Methode customElements.whenDefined(...) . Er erhält den Namen des Element-Tags und gibt das Versprechen zurück, das nach der Registrierung des Elements aufgelöst wurde.

 customElements.whenDefined('my-custom-element').then(_ => { console.log('My custom element is defined'); }); 

Beispielsweise müssen Sie möglicherweise die Registrierung eines Elements verzögern, bis seine untergeordneten Elemente deklariert sind. Eine solche Verhaltensweise kann äußerst nützlich sein, wenn das Projekt verschachtelte Benutzerelemente enthält. Manchmal kann sich ein Elternteil auf die Implementierung untergeordneter Elemente verlassen. In diesem Fall müssen Sie sicherstellen, dass Kinder vor dem Elternteil registriert sind.

Shadow dom


Wie bereits erwähnt, sind benutzerdefinierte Elemente und das Shadow DOM komplementäre Technologien. Mit der ersten können Sie die JS-Logik in Benutzerelementen kapseln, und mit der zweiten können Sie isolierte Umgebungen für DOM-Fragmente erstellen, die nicht von dem betroffen sind, was sich außerhalb von ihnen befindet. Wenn Sie der Meinung sind, dass Sie das Shadow DOM-Konzept besser verstehen müssen, werfen Sie einen Blick auf eine unserer vorherigen Veröffentlichungen .

So verwenden Sie das Schatten-DOM für ein benutzerdefiniertes Element:

 class MyCustomElement extends HTMLElement { // ... constructor() {   super();   let shadowRoot = this.attachShadow({mode: 'open'});   let elementContent = document.createElement('div');   shadowRoot.appendChild(elementContent); } // ... }); 

Wie Sie sehen, spielt der Aufruf von this.attachShadow eine Schlüsselrolle.

Muster


In einem unserer vorherigen Artikel haben wir ein wenig über Vorlagen gesprochen, obwohl sie tatsächlich eines separaten Artikels würdig sind. Hier sehen wir uns ein einfaches Beispiel für das Einbetten von Vorlagen in benutzerdefinierte Elemente an, wenn diese erstellt werden. Mit dem <template> können Sie also das DOM-Fragment beschreiben, das vom Parser verarbeitet, aber nicht auf der Seite angezeigt wird:

 <template id="my-custom-element-template"> <div class="my-custom-element">   <input type="text" class="email" />   <button class="submit"></button> </div> </template> 

So wenden Sie eine Vorlage in einem benutzerdefinierten Element an:

 let myCustomElementTemplate = document.querySelector('#my-custom-element-template'); class MyCustomElement extends HTMLElement { // ... constructor() {   super();   let shadowRoot = this.attachShadow({mode: 'open'});   shadowRoot.appendChild(myCustomElementTemplate.content.cloneNode(true)); } // ... }); 

Wie Sie sehen können, gibt es eine Kombination aus einem benutzerdefinierten Element, einem Schatten-DOM und Vorlagen. Dadurch konnten wir ein Element erstellen, das in seinem eigenen Raum isoliert ist und in dem die HTML-Struktur von der JS-Logik getrennt ist.

Stilisierung


Bisher haben wir nur über JavaScript und HTML gesprochen und CSS ignoriert. Deshalb gehen wir jetzt auf das Thema Stile ein. Natürlich brauchen wir eine Möglichkeit, benutzerdefinierte Elemente zu formatieren. Stile können im Shadow DOM hinzugefügt werden, aber dann stellt sich die Frage, wie solche Elemente beispielsweise von außen formatiert werden können - wenn sie nicht von der Person verwendet werden, die sie erstellt hat. Die Antwort auf diese Frage ist recht einfach: Benutzerdefinierte Elemente werden genauso wie integrierte Elemente gestaltet.

 my-custom-element { border-radius: 5px; width: 30%; height: 50%; // ... } 

Beachten Sie, dass externe Stile Vorrang vor in einem Element deklarierten Stilen haben und diese überschreiben.

Möglicherweise haben Sie gesehen, wie Sie, wenn eine Seite auf dem Bildschirm angezeigt wird, irgendwann nicht stilisierten Inhalt darauf beobachten können (dies wird als FOUC - Flash Of Unstyled Content bezeichnet). Sie können dieses Phänomen vermeiden, indem Sie Stile für nicht registrierte Komponenten festlegen und beim Registrieren einige visuelle Effekte verwenden. Dazu können Sie den Selektor :defined . Sie können dies beispielsweise folgendermaßen tun:

 my-button:not(:defined) { height: 20px; width: 50px; opacity: 0; } 

Unbekannte Elemente und undefinierte Benutzerelemente


Die HTML-Spezifikation ist sehr flexibel und ermöglicht es Ihnen, alle Tags zu deklarieren, die Sie für den Entwickler benötigen. Wenn das Tag vom Browser nicht erkannt wird, wird es vom Parser als HTMLUnknownElement :

 var element = document.createElement('thisElementIsUnknown'); if (element instanceof HTMLUnknownElement) { console.log('The selected element is unknown'); } 

Bei der Arbeit mit benutzerdefinierten Elementen gilt ein solches Schema jedoch nicht. , ? , , HTMLElement .

 var element = document.createElement('this-element-is-undefined'); if (element instanceof HTMLElement) { console.log('The selected element is undefined but not unknown'); } 

HTMLElement HTMLUnknownElement , , , , - . , , , . div . .


Chrome 36+. API Custom Components v0, , , , . API, , — . API Custom Elements v1 Chrome 54+ Safari 10.1+ ( ). Mozilla v50, , . , Microsoft Edge API. , , webkit. , , , — IE 11.


, , , customElements
window :

 const supportsCustomElements = 'customElements' in window; if (supportsCustomElements) { // API Custom Elements   } 

:

 function loadScript(src) { return new Promise(function(resolve, reject) {   const script = document.createElement('script');   script.src = src;   script.onload = resolve;   script.onerror = reject;   document.head.appendChild(script); }); } //    -    . if (supportsCustomElements) { //    ,    . } else { loadScript('path/to/custom-elements.min.js').then(_ => {   //   ,     . }); } 

Zusammenfassung


, :

  • HTML- JavaScript-, , CSS-.
  • HTML- ( , ).
  • . , — JavaScript, HTML, CSS, , , .
  • - (Shadow DOM, , , ).
  • , .
  • , .

, Custom Elements v1 , , , , , .

Liebe Leser! ?

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


All Articles