Webkomponenten Teil 3: HTML-Vorlagen und Importe

Eintrag

Grüße an Kollegen. Dieser Artikel ist der dritte und letzte Artikel in einer Reihe von Artikeln über Webkomponenten. Die ersten beiden Artikel finden Sie unter:


Webkomponenten. Teil 1: Benutzerdefinierte Elemente
Webkomponenten Teil 2: Shadow DOM

In diesem Artikel wird das <template> -Element sowie HTML-Importe behandelt.



HTML-Vorlagenelement

Das <template> -Element ist ein Tool, mit dem Sie Inhalte auf der Clientseite speichern können, ohne sie auf der Seite zu rendern, sie jedoch während der Ausführung über JavaScript anzeigen können.


Beim Parsen einer Seite wird der Inhalt eines Elements ausschließlich im Hinblick auf die Inhaltsüberprüfung verarbeitet, jedoch ohne es zu rendern (gemäß der Spezifikation repräsentiert dieses Element beim Rendern nichts). Der Inhalt des Elements kann aus Skripten geklont und in das Dokument eingefügt werden. Dies wird sowohl unabhängig für die Standardisierung als auch beim Erstellen von Webkomponenten verwendet.


Inhalt <Vorlage>

Für den Inhalt der <Vorlage> sowie für alle Knoten ohne Browserkontext gelten keine Konformitätsanforderungen, mit Ausnahme der Anforderungen für die Richtigkeit der HTML- und XML-Syntax. Dies bedeutet, dass Sie beispielsweise im Inhalt der Vorlage das img-Element angeben können, ohne den Wert der Attribute src und alt anzugeben.


<template> <div> <img src="{{src}}" alt="{{alt}}"> </div> </template> 

Außerhalb des <template> -Elements ist eine solche Syntax jedoch nicht gültig. In diesem Fall stellt das Überspringen des schließenden Tags </ div> eine Verletzung der HTML-Syntax dar und gilt nicht für den Inhalt von <template>.


Alle im HTML-Code im <template> -Tag angegebenen Elemente sind keine untergeordneten Elemente.


Browser erstellen beim Erstellen eines <template> -Elements ein DocumentFragment, dessen Dokument das sogenannte ist Angemessener Eigentümerinhalt für Vorlageninhalte, bestimmt durch diesen Algorithmus , das Dokument, in dem <Vorlage> angegeben ist, und gibt den Wert der von DocumentFragment erstellten .content- Eigenschaft an.


Das heißt, die .content- Eigenschaft des Vorlagenelements enthält ein DocumentFragment, und die Elemente, die im HTML-Code in den <template> -Tags angegeben wurden, sind untergeordnete Elemente dieses DocumentFragments.


In diesem Fall kann das <template> -Element wie jedes andere mit untergeordneten Elementen ( appendChild () ) hinzugefügt werden. Dies wird jedoch als Verstoß gegen das Vorlageninhaltsmodell angesehen.


Vorlage zum Klonen

Beim Klonen des Inhalts einer Vorlage ist zu beachten, dass das erste Argument für .cloneNode ([deep])
oder der zweite in .importNode (externalNode, deep) muss übertragen werden (gemäß der Spezifikation sollte keine weitere Ausführung erfolgen, wenn das Argument nicht übergeben wird).


Übrigens, obwohl die meisten Beispiele .cloneNode () verwenden, ist auch die Verwendung von .importNode () möglich. Der einzige Unterschied besteht darin, wann das Dokument aktualisiert wird (für .cloneNode () - nach dem Aufruf von appendChild (); für .importNode () - nach dem Klonen).


Zeigen Sie mir den Code ©

Die Verwendung von Vorlagen ist wirklich sehr einfach. Ich werde das Beispiel der Komponenten der Registerkarte fortsetzen, mit deren Code ich in den Beispielen früherer Artikel gearbeitet habe.


Zunächst erstelle ich zwei <template> -Elemente im HTML-Markup und übertrage das Markup in die Elemente .render () der Klassen TabNavigationItem und TabContentItem (ich habe auch einige Stile geändert, dies hat jedoch keine Auswirkungen auf die Funktionalität):


  <template id="tab-nav"> <style> :host{ padding: 10px; background-color: rgb(81,180,186); transition: background-color 1s; text-align: center; } :host-context(.active) { background-color: rgb(93, 209, 216); } a{ text-decoration: none; color: rgb(3,32,40); } </style> <a href="#${this._target}"><slot></slot></a> </template> 

und:


  <template id="tab-content"> <style> :host { display: none; padding: 20px; width: 100%; background-color: rgb(255,212,201); } :host-context(.active){ display: block; } </style> <div><slot></slot></div> </template> 

Im Konstruktor jeder Klasse werde ich die Template-Eigenschaft speichern. Für TabNavigationItem ist dies:


  this.template = document.getElementById('tab-nav'); 

a für TabContentItem:


  this.template = document.getElementById('tab-content'); 

In der render () -Methode jeder dieser Klassen werde ich nach dem Löschen des .innerHTML-Eintrags den folgenden Code hinzufügen:


  const content = this.template.content.cloneNode(true); this.shadowRoot.appendChild(content); 

Den resultierenden Code finden Sie hier.


In diesem Beispiel werden beide Vorlagen in HTML angegeben, was umständlich und nicht summend aussieht. Dies bringt uns reibungslos zum Thema:


HTML-Importe

Importe sind HTML-Dokumente, die durch ein anderes HTML-Dokument als externe Ressourcen verbunden sind. Das System der Beziehungen zwischen Dokumenten ist im Entwurf der Spezifikation gut beschrieben und nicht Gegenstand dieses Artikels.

Das allgemeine Schema ist im Bild sichtbar:


.

Um Importe zu implementieren, wurde HTML-Link-Typen (Werte des Attributs rel) ein neuer Typ hinzugefügt.


Das im Wert des rel-Attributs des <link> -Elements selbst angegebene Importwort erstellt einen Link zur importierten Ressource (der Standardtyp der Ressource ist text / html).


Das <link> -Element kann ein asynchrones Attribut haben.


Die durch die Entwurfsspezifikationen angebotenen Erweiterungen werden in der HTMLLinkElement-API angeboten: Eine schreibgeschützte Importeigenschaft wird hinzugefügt, die das importierte Dokument enthält.


Eine Eigenschaft kann in zwei Fällen null enthalten: Wenn <link> keinen Import darstellt oder <link> nicht im Dokument enthalten ist.


In der Spezifikation wird separat angegeben, dass immer dasselbe Objekt zurückgegeben werden soll.


Im Zusammenhang mit Importen gibt es ein sogenanntes Masterdokument, das gleichzeitig Ressourcen importiert, ohne die importierte Ressource eines anderen zu sein.

Die ContentSecurityPolicy eines solchen Dokuments sollte alle Importe einschränken. Wenn das Headerfeld für die Inhaltssicherheit auf Import festgelegt ist, muss der Browser die Richtlinie des Masterdokuments für das importierte Dokument erzwingen.


In der Praxis

Für die Registerkartenkomponente erstelle ich einen Vorlagenordner. Darin werde ich zwei Dateien erstellen, in die ich das Komponenten-Markup übertragen werde.


  <!--templates/tab-content.html--> <template id="tab-content"> <style> :host { display: none; padding: 20px; width: 100%; background-color: rgb(255,212,201); } :host-context(.active){ display: block; } </style> <div><slot></slot></div> </template> <!--templates/tab-nav.html--> <template id="tab-nav"> <style> :host{ padding: 10px; background-color: rgb(81,180,186); transition: background-color 1s; text-align: center; } :host-context(.active) { background-color: rgb(93, 209, 216); } a{ text-decoration: none; color: rgb(3,32,40); } </style> <a href="#${this._target}"><slot></slot></a> </template> 

Im <head> der Datei index.html importiere ich die Vorlagen:


  <link rel="import" href="templates/tab-nav.html" id="tab-nav"> <link rel="import" href="templates/tab-content.html" id="tab-content"> 

Ich füge den <link> -Elementen ID-Attribute hinzu, da ich von js aus auf sie zugreifen muss.
Um in den Konstruktoren der Klassen TabNavigationItem und TabContentItem das Vorlagendokument abzurufen, muss ich nur das entsprechende <link> -Element suchen und zu seiner import-Eigenschaft wechseln. Danach suche ich nach der Vorlage, die bereits im importierten Dokument enthalten ist:


  class TabNavigationItem extends HTMLElement { constructor() { super(); this._target = null; this.attachShadow({mode: 'open'}); const templateImport = document.getElementById('tab-nav').import; this.template = templateImport.getElementById('tab-nav'); } //... } class TabContentItem extends HTMLElement { constructor() { super(); this._target = null; this.attachShadow({mode: 'open'}); const templateImport = document.getElementById('tab-content').import; this.template = templateImport.getElementById('tab-content'); } //... } 

Die endgültige Version finden Sie hier .


Informationen zum Support

Unterstützung für HTML-Vorlagen: Edge C 16, Firefox C 59, Chrome C 49, Safari C 11.
Mit Importunterstützung trauriger: Chrome c 49.
Daher sind die Beispiele aus diesem Artikel nur im neuesten Chrome zu sehen.


Es gibt Polyphile:


Webkomponenten
Polymer-Projekt

Lesen Sie mehr über Vorlagen und Importe:

HTML-Spezifikation
HTML5-Spezifikation
HTML Importiert Entwurfsspezifikationen

Das ist alles, danke fürs Zuschauen,
Tanya

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


All Articles