Inicio rápido con WebComponents

Los componentes web son un conjunto de estándares que definen interfaces de software para organizar la arquitectura de componentes. Todos ellos están implementados en versiones modernas de navegadores, es decir. no requieren la conexión de bibliotecas o transpiladores de código; sin embargo, si necesita compatibilidad, por ejemplo, con Internet Explorer 11, probablemente todavía necesite usar bibliotecas y transpiladores.

Este artículo está dirigido al nivel inicial de capacitación y desarrolladores que tienen experiencia con uno u otro marco front-end, pero quizás, gracias a algunos trucos, será interesante para expertos experimentados.

Todos los experimentos citados a continuación fueron probados en Chrome y Firefox puede que ni siquiera sean las versiones más recientes.

Entonces comencemos.

Primero, cree un directorio para el proyecto y vaya a él.

mkdir mywebcomp cd mywebcomp 

Ejecutar:

 npm init 

en este directorio respondiendo todas las preguntas de forma predeterminada.

Cree un archivo index.html con los contenidos más simples en el directorio.

 <html lang="en"> <body> </body> </html> 

Agregue una etiqueta para un elemento, el nombre debe contener un guión, esta es una señal para que el subsistema CusomElements intente definir este elemento como una construcción sobre los estándares.

 <html lang="en"> <body> <my-webcomp></my-webcomp> </body> </html> 

Agregue una clase de controlador a la etiqueta del script .

 <script type="module"> class MyWebComp extends HTMLElement { connectedCallback() { this.insertAdjacentHTML('beforeEnd', `<div>Hello</div>`) } } customElements.define('my-webcomp', MyWebComp); </script> 

En la etiqueta de script modular, definimos una nueva clase que, utilizando el método customElements.define () , la definió detrás de la etiqueta my-webcomp . Y al agregar el código al método connectedCallback () , proporcionamos su llamada al agregar la implementación del componente al árbol. El resultado ya se puede ver en el navegador:



Sin embargo, colocar el diseño html directamente en el código, si es conveniente para piezas pequeñas, generalmente no es correcto, lo cual es especialmente cierto cuando las piezas crecen a un tamaño decente. Por ejemplo, en un formulario con 20 elementos, que superar a los subcomponentes también puede no ser siempre conveniente. Por lo tanto, para empezar, presentaremos el diseño en la plantilla, que se ubicará en el mismo html, aunque nada nos impedirá cargarlo desde un archivo separado si es necesario.

 <html lang="en"> <body> <template id="myWebCompTemplate"> <div>Hello</div> </template> <my-webcomp></my-webcomp> <script type="module"> class MyWebComp extends HTMLElement { connectedCallback() { let tplEl = document.querySelector('#myWebCompTemplate'); let html = document.importNode(tplEl.content, true); this.appendChild(html); } } customElements.define('my-webcomp', MyWebComp); </script> </body> </html> 

En el código del componente, reemplazamos la inserción de una cadena con html al recibir un elemento de plantilla por id. Importar, es decir crear una copia de este elemento y vincularlo al contenido del actual.

id se nombra en notación camelCase desde Todos los identificadores de elementos se lanzan al espacio de nombres global cuando se utilizan guiones u otros especiales. El acceso de los personajes a ellos puede ser menos elegante. Es decir en su lugar podríamos:

  let tplEl = document.querySelector('#myWebCompTemplate'); let html = document.importNode(tplEl.content, true); 

escribe en una línea:

 let html = document.importNode(myWebCompTemplate.content, true); 

y este código funcionaría de la misma manera, pero se considera no muy seguro. Además, si asignamos un identificador a nuestro elemento, podemos acceder a él desde cualquier parte del contexto como una instancia desde el espacio de nombres global llamando a métodos y obteniendo valores de propiedad.
Por ejemplo, así:

 <my-webcomp id="myWebComp"></my-webcomp> <script type="module"> class MyWebComp extends HTMLElement { connectedCallback() { let html = document.importNode(myWebCompTemplate.content, true); this.appendChild(html); } } customElements.define('my-webcomp', MyWebComp); </script> <script type="module"> myWebComp.showMessage(); </script> 

En este escenario, la alerta se mostrará inmediatamente cuando se cargue la página.

Ahora colgaremos un controlador de clic del mouse para nuestro componente que mostrará un mensaje de alerta.

 <my-webcomp id="myWebComp" onclick="this.showMessage(event)"></my-webcomp> <script type="module"> class MyWebComp extends HTMLElement { connectedCallback() { let html = document.importNode(myWebCompTemplate.content, true); this.appendChild(html); } showMessage(event) { alert("This is the message"); console.log(event); } } customElements.define('my-webcomp', MyWebComp); </script> 

Ahora, cuando haga clic en un mensaje, tendremos una reacción a las acciones del usuario.



El argumento del método showMessage () también declara un objeto de evento que almacena datos de eventos, como las coordenadas de un clic o un enlace al elemento en sí.

A menudo, cada elemento en particular debe configurarse de una manera única para ello, esto se puede hacer usando atributos.

Agregue una segunda instancia del elemento y defina para cada una de ellas diferentes propiedades de nombre de saludo cuyos valores se mostrarán cuando se haga clic en el elemento.

 <my-webcomp id="myWebComp" greet-name="John" onclick="this.showMessage(event)"></my-webcomp> <my-webcomp id="myWebComp2" greet-name="Josh" onclick="this.showMessage(event)"></my-webcomp> <script type="module"> class MyWebComp extends HTMLElement { connectedCallback() { let html = document.importNode(myWebCompTemplate.content, true); this.appendChild(html); } showMessage(event) { alert("This is the message " + this.getAttribute('greet-name')); console.log(event); } } customElements.define('my-webcomp', MyWebComp); </script> 

Ahora, cuando hace clic en el primero, se mostrará "Este es el mensaje para John", y en el segundo "Este es el mensaje para Josh".

Puede suceder que el atributo no se use en el procesamiento de eventos, sino que se represente directamente en la plantilla, para esto agregaremos id al elemento de destino y sustituiremos el valor de api inmediatamente después de representar una copia del objeto de plantilla.

 <template id="myWebCompTemplate"> <div id="helloLabel">Hello</div> </template> <my-webcomp id="myWebComp" greet-name="John" onclick="this.showMessage(event)"></my-webcomp> <my-webcomp id="myWebComp2" greet-name="Josh" onclick="this.showMessage(event)"></my-webcomp> <script type="module"> class MyWebComp extends HTMLElement { connectedCallback() { let html = document.importNode(myWebCompTemplate.content, true); this.appendChild(html); this.querySelector('#helloLabel').textContent += ' ' + this.getAttribute('greet-name'); } showMessage(event) { alert("This is the message " + this.getAttribute('greet-name')); console.log(event); } } customElements.define('my-webcomp', MyWebComp); </script> 

Resulta así:



En lugar de .textContent, puede ser .innerHTML o puede llamar al mismo método .insertAdarestHTML () en el objeto desde el selector que hicimos al principio.

Durante mucho tiempo, el uso de ID se consideró una mala forma, ya que en cantidades significativas de código podrían duplicarse, lo que provocó colisiones. Sin embargo, con el advenimiento de la tecnología de árbol de sombra, puede aislar el contenido interno de un elemento utilizando identificadores, estilos y otros recursos sin temor. Para los componentes web, el árbol de sombra se habilita de la siguiente manera:

  this.attachShadow({mode: 'open'}); 

Ahora la verdad es que todas las llamadas DOM a esto tendrán que ser reemplazadas por this.shadowRoot, ya que no hay tantas.

 <script type="module"> class MyWebComp extends HTMLElement { connectedCallback() { let html = document.importNode(myWebCompTemplate.content, true); this.attachShadow({mode: 'open'}); this.shadowRoot.appendChild(html); this.shadowRoot.querySelector('#helloLabel').textContent += ' ' + this.getAttribute('greet-name'); } showMessage(event) { alert("This is the message " + this.getAttribute('greet-name')); console.log(event); } } customElements.define('my-webcomp', MyWebComp); </script> 

Visualmente, el trabajo de este código no volverá a cambiar de ninguna manera, pero ahora no habrá helloLabel en el espacio de nombres global, y la página ya tiene 2 elementos con este identificador. Y puede acceder a ellos, por ejemplo, así:

 myWebComp.shadowRoot.getElementById('helloLabel'); 

y luego si no cierra el árbol pasando el atributo correspondiente en el método .attachShadow () .

Obtuvimos bastante código y colocarlo directamente en el archivo html tampoco es muy correcto. Por lo tanto, crearemos el archivo my-webcomp.js y le transferiremos nuestra clase con la declaración de exportación, y agregaremos la importación de esta clase en la etiqueta del script para obtener esto:

 <script type="module"> import { MyWebComp } from "./my-webcomp.js"; customElements.define('my-webcomp', MyWebComp); myWebComp.shadowRoot.getElementById('helloLabel'); </script> 

Esto no afectará el rendimiento, pero ahora toda nuestra lógica de negocios está separada en .js, la configuración se realiza en atributos html y los sistemas de navegador modular y de componentes se encargan de la inicialización asincrónica modular.

Sin embargo, a partir de ahora, abrir index.html como local para el desarrollo fallará, porque el navegador bloqueará la descarga del script desde el sistema de archivos. Si tiene nodejs, puede poner el servidor web más simple:

 npm i http-server -g 

y ejecútelo con el comando http-server en el directorio del proyecto, al inicio le indicará al host y al puerto desde el que puede abrir la página

 http://127.0.0.1:8080 

Que ahora será la dirección de la página de depuración con nuestro elemento.

Escribir pruebas también es importante para el desarrollo; ayudan a mantener el código viable durante el desarrollo de sus componentes. Para probar los componentes web, puede usar mocha en modo de inicio desde el navegador.

Agregar paquetes

 npm i mocha chai wct-mocha --save-dev 

Para hacer esto, cree el directorio de prueba y agregue el siguiente archivo all.html :

 <!doctype html> <html> <head> <meta charset="utf-8"> <script src="../node_modules/mocha/mocha.js"></script> <script src="../node_modules/chai/chai.js"></script> <script src="../node_modules/wct-mocha/wct-mocha.js"></script> </head> <body> <script> WCT.loadSuites([ 'my-webcomp.tests.html', ]); </script> </body> </html> 

Copie nuestro index.html para probar / dándole el nombre my-webcomp.tests.html y agregue el mismo contenido de encabezado que en all.html .

Sin embargo, ahora necesitaremos reemplazar la inicialización y las manipulaciones habituales con las realizadas como parte de la ejecución de la prueba:

 <script type="module"> import { MyWebComp } from "../my-webcomp.js"; customElements.define('my-webcomp', MyWebComp); suite('MyWebComp', () => { test('is MyWebComp', () => { const element = document.getElementById('myWebComp'); chai.assert.instanceOf(element, MyWebComp); }); }); </script> 

Ahora al entrar

 http://127.0.0.1:8080/test/all.html 

Se mostrará un informe de prueba.



Pero es posible que deba ejecutar las pruebas automáticamente y en diferentes navegadores necesita instalar una utilidad especial:

 sudo npm install --global web-component-tester --unsafe-perm 

y correr así:

 wct --npm 

Esta línea se puede agregar a la sección de prueba del archivo package.json y ejecutarse como:

 npm test 



Se recomienda probar cada método de clase significativo como parte de una prueba separada. Si es necesario hacer una inicialización común para cada uno, debe definirse en el método suiteSetup () :

 suiteSetup(() => { }); 

dentro de la suite.

Probablemente esto sea suficiente por primera vez, tenemos un proyecto mínimo que si resuelve una tarea específica, no se avergonzaría de hacerlo.

 npm publish 

o al menos

 git push 

Todavía no hay tantos libros sobre el tema, pero toda la documentación extensa se encuentra fácilmente de acuerdo con los componentes web, elementos personalizados, ShadowDOM, etiqueta de plantilla nativa, eventos personalizados.

Puede verificar su código con el repositorio: https://bitbucket.org/techminded/mywebcomp

Aquí puede encontrar una continuación del tema que demuestra cómo interactuar entre los componentes mediante el uso de eventos .

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


All Articles