Lorsque je suis allé à des conférences et que j'ai vu des présentations sur le thème des composants Web, j'ai toujours pensé que c'était non seulement élégant, mais aussi assez difficile. Mille lignes de JavaScript pour stocker seulement 4 lignes de HTML. L'orateur cachait inévitablement une énorme quantité de code JS derrière des choses simples, ou plongeait dans des détails complexes, puis mes yeux ont commencé à se fermer avec l'ennui et j'ai commencé à me demander si mon allocation quotidienne couvrait le coût des collations.
Cependant, sur un projet récent conçu pour apprendre facilement le HTML (bien sûr, en ajoutant des zombies et des blagues idiotes), j'ai décidé qu'il était nécessaire de décrire chaque élément HTML de la spécification. En dehors de cette conférence, j'ai commencé par l'introduction <slot>
et <template>
les éléments, et quand je voulais écrire quelque chose d'intéressant à leur sujet dans le projet, je devais approfondir le sujet.
Et au fur et à mesure que j'allais plus loin, j'ai réalisé que les composants Web sont plus faciles que je ne le pensais.
Soit les composants Web ont parcouru un long chemin depuis que je rêvais de grignoter lors d'une conférence, soit je laisse ma peur initiale m'empêcher de vraiment les connaître, ou peut-être les deux.
Je suis ici pour vous dire que oui, vous pouvez créer un composant Web. Mettons la peur et même des collations à l'extérieur de la porte pour tout rassembler.
Commençons par un <template>
<template>
est un élément HTML qui nous permet de créer un modèle (structure HTML pour les composants Web).
Le code
<template>
<p>The Zombies are coming!</p>
</template>
L'élément <template>
est très important car il vous permet de tout garder ensemble. C'est comme une base pour votre maison, une base à partir de laquelle tout ce que nous appelons un bâtiment fini commence à se construire. Utilisons ce petit bout de code pour notre <apocalyptic-warning>
composant qui nous avertit de l'apocalypse zombie à venir.
Ensuite, il y a le composant <slot>
<slot>
est juste un élément HTML, tout comme <template>
. Mais dans notre cas, il <slot>
configure ce qu'il <template>
affiche sur la page.
Le 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
, , , -, . , , - , , .
C'est tout. De quoi avez-vous le plus peur maintenant: les composants Web ou une apocalypse zombie? Dans un passé pas si lointain, j'aurais pu dire que les composants Web, mais maintenant les zombies sont la seule chose qui m'inquiète (enfin, mon allocation quotidienne couvrira-t-elle les coûts des collations).