Wenn ich zu Konferenzen ging und Präsentationen zum Thema Webkomponenten sah, dachte ich immer, dass dies nicht nur elegant, sondern auch ziemlich schwierig ist. Tausend Zeilen JavaScript zum Speichern von nur 4 Zeilen HTML. Der Sprecher versteckte entweder unweigerlich eine große Menge JS-Code hinter einfachen Dingen oder tauchte in komplexe Details ein, dann schlossen sich meine Augen vor Langeweile und ich begann darüber nachzudenken, ob mein Tagegeld die Kosten für Snacks deckte.
Bei einem kürzlich durchgeführten Projekt zum einfachen Erlernen von HTML (natürlich durch Hinzufügen von Zombies und albernen Witzen) entschied ich jedoch, dass jedes HTML-Element in der Spezifikation beschrieben werden muss. Abgesehen von dieser Konferenz begann ich zunächst mit der Einführung <slot>
und <template>
den Elementen, und als ich im Projekt etwas Interessantes darüber schreiben wollte, musste ich mich mit dem Thema befassen.
Und als ich tiefer ging, stellte ich fest, dass Webkomponenten einfacher sind als ich dachte.
Entweder haben Webkomponenten einen langen Weg zurückgelegt, seit ich davon geträumt habe, auf einer Konferenz zu naschen, oder ich habe meine anfängliche Angst daran gehindert, sie wirklich kennenzulernen, oder vielleicht beides.
Ich bin hier, um Ihnen zu sagen , dass Sie eine Webkomponente erstellen können. Lassen Sie uns Angst und sogar Snacks vor die Tür stellen, um alles zusammenzubringen.
Beginnen wir mit einer <Vorlage>
<template>
ist ein HTML-Element, mit dem wir eine Vorlage erstellen können (HTML-Struktur für Webkomponenten).
Der Code
<template>
<p>The Zombies are coming!</p>
</template>
Das Element <template>
ist sehr wichtig, weil Sie so alles zusammenhalten können. Es ist wie eine Basis für Ihr Zuhause, eine Basis, von der aus alles, was wir als fertiges Gebäude bezeichnen, zu bauen beginnt. Verwenden wir diesen kleinen Codeausschnitt für unsere <apocalyptic-warning>
Komponente, die uns über die bevorstehende Zombie-Apokalypse informiert.
Dann gibt es die <slot> -Komponente
<slot>
ist nur ein HTML-Element, genau wie <template>
. In unserem Fall wird jedoch <slot>
konfiguriert, was <template>
auf der Seite angezeigt wird.
Der Code
<template>
<p>The <slot>Zombies</slot> are coming!</p>
</template>
"Zombies" ( ?) <template>
. , . "Zombies".
<slot>
placeholder
. placeholder
, , - placeholder
. - name
.
<template>
<p>The <slot name="whats-coming">Zombies</slot> are coming!</p>
</template>
name
- , <template>
. "whats-coming" . , -, <slot>
, - , , .
-
, , ( : JS , ).
<apocalyptic-warning>
<span slot="whats-coming">Halitosis Laden Undead Minions</span>
</apocalyptic-warning>
<template>
<p>The <slot name="whats-coming">Zombies</slot> are coming!</p>
</template>
, ? <apocalyptic-warning>
, HTML . <span>
"whats-coming". <span>
"Zombies", .
, - , HTML , . , , -.
? , ? , . , <slot>
, JavaScript.
, JavaScript , , , , . , , .
-, -. : , .
, .
// -
customElements.define("apocalyptic-warning", class extends HTMLElement {
// , HTML
// ,
constructor() {
// , . HTMLElement. HTML .
super();
// <template> `warinng`
let warning = document.getElementById("warningtemplate");
// `mywarning`
let mywarning = warning.content;
const shadowRoot = this.attachShadow({mode: "open"}).appendChild(mywarning.cloneNode(true));
}
});
, .
const shadowRoot = this.attachShadow({mode: "open"}).appendChild(mywarning.cloneNode(true));
. -, - (this) , Shadow DOM.{ mode: open }
, JavaScript :root
Shadow DOM , - . Shadow DOM ( : HTML Node). , . , Shadow DOM , <slot>
slot , .
. -, , .
JS:
customElements.define('apocalyptic-warning',
class extends HTMLElement {
constructor() {
super();
let warning = document.getElementById('warningtemplate');
let mywarning = warning.content;
const shadowRoot = this.attachShadow({mode: 'open'}).appendChild(mywarning.cloneNode(true));
}
});
HTML:
<p>The Apocalypse will never happen!</p>
<apocalyptic-warning>
<span slot="whats-coming">Undead</span>
</apocalyptic-warning>
<apocalyptic-warning>
<span slot="whats-coming">Halitosis Laden Zombie Minions</span>
</apocalyptic-warning>
<template id="warningtemplate">
<style>
p {
background-color: pink;
padding: 0.5em;
border: 1px solid red;
}
</style>
<p>The <slot name="whats-coming">Zombies</slot> are coming!</p>
</template>
: Codepen
, . , CSS. , <style>
<template>
.
<template id="warningtemplate">
<style>
p {
background-color: pink;
padding: 0.5em;
border: 1px solid red;
}
</style>
<p>The <slot name="whats-coming">Zombies</slot> are coming!</p>
</template>
, , Shadow DOM.
, , , , , Shadow DOM. , Shadow DOM DOM , . - , DOM .
, , <style>,
<slot>
. , . - , CSS , , . , -, CSS.
apocalyptic-warning span {
color: blue;
}
, CSS <template>
.
JavaScript , , , , <zombie-profile>.
customElements.define("zombie-profile",
class extends HTMLElement {
constructor() {
super();
let profile = document.getElementById("zprofiletemplate");
let myprofile = profile.content;
const shadowRoot = this.attachShadow({mode: "open"}).appendChild(myprofile.cloneNode(true));
}
}
);
HTML CSS.
<template id="zprofiletemplate">
<style>
img {
width: 100%;
max-width: 300px;
height: auto;
margin: 0 1em 0 0;
}
h2 {
font-size: 3em;
margin: 0 0 0.25em 0;
line-height: 0.8;
}
h3 {
margin: 0.5em 0 0 0;
font-weight: normal;
}
.age, .infection-date {
display: block;
}
span {
line-height: 1.4;
}
.label {
color: #555;
}
li, ul {
display: inline;
padding: 0;
}
li::after {
content: ', ';
}
li:last-child::after {
content: '';
}
li:last-child::before {
content: ' and ';
}
</style>
<div class="profilepic">
<slot name="profile-image"><img src="https://assets.codepen.io/1804713/default.png" alt=""></slot>
</div>
<div class="info">
<h2><slot name="zombie-name" part="zname">Zombie Bob</slot></h2>
<span class="age"><span class="label">Age:</span> <slot name="z-age">37</slot></span>
<span class="infection-date"><span class="label">Infection Date:</span> <slot name="idate">September 12, 2025</slot></span>
<div class="interests">
<span class="label">Interests: </span>
<slot name="z-interests">
<ul>
<li>Long Walks on Beach</li>
<li>brains</li>
<li>defeating humanity</li>
</ul>
</slot>
</div>
<span class="z-statement"><span class="label">Apocalyptic Statement: </span> <slot name="statement">Moooooooan!</slot></span>
</div>
</template>
CSS <zombie-profile>
CSS. , , , <template>
.
zombie-profile {
width: calc(50% - 1em);
border: 1px solid red;
padding: 1em;
margin-bottom: 2em;
display: grid;
grid-template-columns: 2fr 4fr;
column-gap: 20px;
}
zombie-profile img {
width: 100%;
max-width: 300px;
height: auto;
margin: 0 1em 0 0;
}
zombie-profile li, zombie-profile ul {
display: inline;
padding: 0;
}
zombie-profile li::after {
content: ', ';
}
zombie-profile li:last-child::after {
content: '';
}
zombie-profile li:last-child::before {
content: ' and ';
}
:
: Codepen
, , , -, . , , - , , .
Das ist alles. Wovor haben Sie jetzt mehr Angst: Webkomponenten oder eine Zombie-Apokalypse? In der nicht allzu fernen Vergangenheit hätte ich sagen können, dass Webkomponenten, aber jetzt sind Zombies das einzige, was mich beunruhigt (Nun, und mein Tagesgeld deckt die Kosten für Snacks).