Cuando fui a conferencias y vi presentaciones sobre el tema de los componentes web, siempre pensé que no solo era elegante, sino también bastante difícil. Mil líneas de JavaScript para almacenar solo 4 líneas de HTML. El orador escondió inevitablemente una gran cantidad de código JS detrás de cosas simples o se sumergió en detalles complejos, luego mis ojos comenzaron a cerrarse por el aburrimiento y comencé a pensar si mi asignación diaria cubría el costo de los bocadillos.
Sin embargo, en un proyecto reciente hecho para aprender HTML fácilmente (por supuesto, agregando zombies y bromas tontas), decidí que era necesario describir cada elemento HTML en la especificación. Aparte de esa conferencia, primero comencé con la introducción <slot>
y <template>
los elementos, y cuando quise escribir algo interesante sobre ellos en el proyecto, tuve que ahondar en el tema.
Y a medida que profundicé, me di cuenta de que los componentes web son más fáciles de lo que pensaba.
O los componentes web han recorrido un largo camino desde que soñé con comer bocadillos en una conferencia, o dejé que mi miedo inicial se interpusiera en el camino para conocerlos realmente, o tal vez ambos.
Estoy aquí para decirte que sí, puedes crear un componente web. Pongamos miedo e incluso bocadillos fuera de la puerta para juntarlo todo.
Comencemos con una <template>
<template>
es un elemento HTML que nos permite crear una plantilla (estructura HTML para componentes web).
El código
<template>
<p>The Zombies are coming!</p>
</template>
El elemento <template>
es muy importante porque te permite mantener todo junto. Es como una base para tu hogar, una base a partir de la cual todo lo que llamamos edificio terminado comienza a construirse. Usemos este pequeño fragmento de código para nuestro <apocalyptic-warning>
componente que nos notifica del próximo apocalipsis zombie.
Luego está el componente <slot>
<slot>
es solo un elemento HTML, como <template>
. Pero en nuestro caso, <slot>
configura lo que <template>
muestra en la página.
El código
<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
, , , -, . , , - , , .
Eso es todo. ¿De qué tienes más miedo ahora: los componentes web o un apocalipsis zombi? En un pasado no muy lejano, podría haber dicho que los componentes web, pero ahora los zombis son lo único que me preocupa (bueno, y mi asignación diaria cubrirá los costos de los bocadillos).