17 noviembre, 2019

Primeros pasos con Web Components

¿Qué es?

En este tutorial, vamos a aprender qué son y cómo crear web components. Se trata de un nuevo estándar HTML5, que incluye cuatro subelementos:

  • Custom elements:  permiten crear tus propias etiquetas personalizadas, permitiendo hacer tu html más semántico.
  • Templates: plantillas html.
  • Shadow DOM: permiten esconder elementos del DOM.
  • HTML Imports: permiten importar código html, donde podremos tener almacenado un componente.

La web oficial se encuentra en:

http://webcomponents.org/

Estos cuatro subelementos se pueden utilizar de forma independiente o pueden combinarse entre sí, que es como suelen usarse, y por ahora sólo funcionan en pocos navegadores, como Google Chrome (ya explicaremos en otra entrada cómo usarlo en el resto de navegadores mediante Polyfills). Vamos a ver ejemplos reales.

 ¿Por dónde empiezo?

Sólo necesitas crear un html, sin ningún requisito inicial. Ve a tu carpeta de proyectos (la que tú elijas, puede estar en tu carpeta de usuario o donde tú quieras, en mi caso, está en D:\desarrollo\web-components) y crea ahí una carpeta, con el nombre que quieras dar al proyecto (en mi caso, «diegorys-hola»). Ahora, crea un archivo index.html con tu editor de texto preferido (yo uso y recomiendo Sublime Text 3). Vamos a escribir un código html inicial:

<!DOCTYPE html>
<html>
<head>
 <meta charset="UTF8">
 <title>Web Component Diegorys</title>
</head>
<body>
 <div>
 Visita
 <a href="http://diegorys.es" title="Ir a diegorys.es" target="_blank">
 diegorys.es
 </a>
 </div>
</body>
</html>

Y a ejecutarlo en el navegador, para ver que se muestra en él el párrafo que hemos puesto.

Ahora, sustituimos el código de dentro del <body> por la etiqueta nueva que queremos crear, <diegorys-hola>. Como resultado, esperamos que este código acabe mostrando lo mismo en el navegador (necesitaremos meter un script antes de que funcione):

<!DOCTYPE html>
<html>
<head>
 <meta charset="UTF8">
 <title>Web Component Diegorys</title>
</head>
<body>
 <diegorys-hola></diegorys-hola>
</body>
</html>

Si lanzamos nuestro proyecto en el navegador, no veremos nada. Vamos a crear nuestro primer Custom elements, sólo con javascript:

<!DOCTYPE html>
<html>
<head>
 <meta charset="UTF8">
 <title>Web Component Diegorys</title>
</head>
<body>
 <diegorys-hola></diegorys-hola>

<script>
 var prototipo = Object.create(HTMLElement.prototype);

prototipo.createdCallback = function() {
 this.textContent = 'diegorys.es';
 }

document.registerElement('diegorys-hola', {
 prototype: prototipo
 });
 </script>
</body>
</html>

Un código un tanto engorroso, ¿no? Pero seguimos adelante, con el segundo subelemento. Vamos a usar Templates para poder meter todo el contenido que teníamos antes. Todo el contenido que se meta entre las etiquetas <template> será ignorado por el navegador (excepto los estilos, que se aplican a toda la web). El código queda así:

<!DOCTYPE html>
<html>
<head>
 <meta charset="UTF8">
 <title>Web Component Diegorys</title>
</head>
<body>
 <diegorys-hola></diegorys-hola>

 <template>
 Visita
 <a href="http://diegorys.es" title="Ir a diegorys.es" target="_blank">
 diegorys.es
 </a>
 </template>
 <script>
 var prototipo = Object.create(HTMLElement.prototype);

 prototipo.createdCallback = function() {
 this.textContent = 'diegorys.es';
 }

 document.registerElement('diegorys-hola', {
 prototype: prototipo
 });
 </script>
</body>
</html>

Y, como hemos dicho, el navegador ignora el template, por lo que el resultado será igual al ejemplo anterior. Para que se vea nuestro mensaje, debemos añadir unas líneas al javascript:

<!DOCTYPE html>
<html>
<head>
 <meta charset="UTF8">
 <title>Web Component Diegorys</title>
</head>
<body>
 <diegorys-hola></diegorys-hola>

 <template>
 <div>
 Visita
 <a href="http://diegorys.es" title="Ir a diegorys.es" target="_blank">
 diegorys.es
 </a>
 </div>
 </template>
 <script>
 var prototipo = Object.create(HTMLElement.prototype);
 var template = document.currentScript.ownerDocument.querySelector('template').content;

 prototipo.createdCallback = function() {
 var clonTemplate = document.importNode(template, true);
 this.appendChild(clonTemplate);
 }

 document.registerElement('diegorys-hola', {
 prototype: prototipo
 });
 </script>
</body>
</html>

El resultado será el del primer ejemplo, pero sólo usando la etiqueta <diegorys-hola>. Olvida todo el código «sucio» que has metido, porque lo moveremos más adelante a otro archivo. Pero antes, puedes probar por ti mismo a duplicar la etiqueta creada, para veas cómo se muestra dos veces el mensaje de que visites mi web:

 <diegorys-hola></diegorys-hola>
 <diegorys-hola></diegorys-hola>

Vamos a dar algo de estilo a nuestra plantilla:

<template>
 <style>
 div {
 background-color: #1e73be;
 color: #FFFFFF;
 padding: 1em;
 }

a {
 color: #FFFFFF;
 }
 </style>
 <div>
 Visita
 <a href="http://diegorys.es" title="Ir a diegorys.es" target="_blank">
 diegorys.es
 </a>
 </div>
 </template>

Vemos cómo cambian los colores para nuestra nueva etiqueta. Pero… ¿qué pasa si metemos otro <div> en nuestro html? Pues, como podemos comprobar, también se le aplican estos estilos, y es algo que no deseamos, ya que queremos que nuestro componente funcione de forma independiente al resto de la web y no afecte a su funcionamiento. Podéis hacer la prueba metiendo un <div> o un <a> dentro del <body>. ¿Cómo solucionamos esto? Con el tercer subelemento, Shadow DOM, que nos permitirá clonar la plantilla de forma oculta en el DOM. Simplemente, reemplazamos esta línea:

this.appendChild(clonTemplate);

por esta otra:

this.createShadowRoot().appendChild(clonTemplate);

Y ahora podemos comprobar cómo el estilo sólo se aplica a nuestro template. Y, si examináis el código generado, veréis cómo ha añadido el template de forma oculta en el DOM, a diferencia de antes.

Hasta ahora, hemos conseguido crear una etiqueta semántica nueva, con la que, con sólo un poco de código «(<diegorys-hola></diegorys-hola>)» somos capaces de generar todo el html que enlaza a nuestra web. Sin embargo, como habréis observado, necesitamos un montón de código extra, bastante complejo y que ensucia nuestro código. Pero, gracias al siguiente subelemento, HTML Imports, podremos llevarnos todo ese código a otro archivo, que será nuestro elemento, y decir a nuestro index que lo importe. Para ello, creamos un segundo archivo, en el mismo directorio del proyecto donde tenemos nuestro index.html, al que llamaremos igual que nuestro componente, con extensión html. En mi caso, será diegorys-hola.html. Nos llevaremos a él todo el código que corresponde a nuestro elemento:

<template>
 <style>
 div {
 background-color: #1e73be;
 color: #FFFFFF;
 padding: 1em;
 }

 a {
 color: #FFFFFF;
 }
 </style>
 <div>
 Visita
 <a href="http://diegorys.es" title="Ir a diegorys.es" target="_blank">
 diegorys.es
 </a>
 </div>
</template>
<script>
 var prototipo = Object.create(HTMLElement.prototype);
 var template = document.currentScript.ownerDocument.querySelector('template').content;

 prototipo.createdCallback = function() {
 var clonTemplate = document.importNode(template, true);
 this.createShadowRoot().appendChild(clonTemplate);
 }

 document.registerElement('diegorys-hola', {
 prototype: prototipo
 });
</script>

Mientras que dejaremos el resto de contenido en el index, añadiendo una línea en el <head>, que importará el componente:

<!DOCTYPE html>
<html>
<head>
 <meta charset="UTF8">
 <title>Web Component Diegorys</title>
 <link rel="import" href="diegorys-hola.html">
</head>
<body>
 <diegorys-hola></diegorys-hola>
</body>
</html>

Como veis, el archivo queda ahora muchísimo más limpio. Sin embargo, si tratáis de ejecutarlo, comprobaréis que no se ve nada en el navegador. Esto es debido a que, para que funcione HTML Import, debemos tener corriendo un sevidor web. Si queréis probarlo, podéis lanzar un servidor PHP con un dominio «webcomponent.dev», siguiendo el tutorial de Cómo configurar sitios web en WampServer.

Descarga

El código lo tengo compartido en mi cuenta de GitHub:

https://github.com/diegorys/diegorys-hola

Podéis verlo en funcionamiento en la siguiente dirección:

http://diegorys.es/ejemplos/webcomponents/diegorys-hola

Conclusión

Mi conclusión, hasta ahora, sobre los web components, es que son muy engorrosos, pero, con todo el potencial que ofrecen, que va muchísimo más allá de este sencillo ejemplo, son el futuro, cada vez más presente. Librerías como Polymer nos harán la vida más fácil para crearlos. Lo veremos en próximas entradas.

Deja un comentario

Este sitio web utiliza cookies para que usted tenga la mejor experiencia de usuario. Si continúa navegando está dando su consentimiento para la aceptación de las mencionadas cookies y la aceptación de nuestra política de cookies, pinche el enlace para mayor información.plugin cookies

ACEPTAR
Aviso de cookies