Elementos personalizados de componentes web

 

 

 

Elementos personalizados de componentes web 1

 

Un tutorial introductorio a los elementos personalizados

Escribí mi primer elemento personalizado usando una biblioteca CSS llamada CSS Doodle. Es una aplicación increíble que usa elementos personalizados para permitirte crear animaciones CSS impresionantes. Eso despertó en mí un deseo completamente nuevo de descubrir cómo funciona esa cosa bajo el capó. Así que decidí analizar más de cerca los componentes web en general, un tema sobre el que muchas personas me pidieron que escribiera.

Los elementos personalizados nos permiten crear nuevas etiquetas HTML.

No podía imaginarme por qué esto podría ser útil hasta que usé la biblioteca CSS Doodle. Después de todo, ya tenemos muchas etiquetas.

Este tutorial cubre la versión 1 de Custom Elements, la última versión del estándar al momento de escribir este artículo.

Usando elementos personalizados podemos crear una etiqueta HTML personalizada con CSS y JavaScript asociados.

No es una alternativa a frameworks como React, Angular o Vue, pero es un concepto completamente nuevo.

El windowobjeto global expone una customElementspropiedad que nos da acceso a un CustomElementRegistryobjeto.

El CustomElementRegistryobjeto

Este objeto tiene varios métodos que podemos usar para registrar elementos personalizados y consultar elementos personalizados ya registrados:

  • define()se utiliza para definir un nuevo elemento personalizado
  • get()se utiliza para obtener el constructor de un elemento personalizado (devuelve undefinedsi no existe)
  • upgrade()para actualizar un elemento personalizado
  • whenDefined()Se utiliza para obtener el constructor de un elemento personalizado. Es similar a get(), pero devuelve una promesa que se resuelve cuando el elemento está disponible.

Cómo crear un elemento personalizado

Antes de poder llamar al window.customElements.define()método, debemos definir un nuevo elemento HTML creando una nueva clase que extienda la clase incorporada HTMLElement:

 

class CustomTitle extends HTMLElement { //...}

Dentro del constructor de clase, vamos a utilizar Shadow DOM para asociar CSS, JavaScript y HTML personalizados a nuestra nueva etiqueta.

De esta manera, todo lo que veremos en el HTML es nuestra etiqueta, pero esto encapsulará mucha funcionalidad.

Comenzamos inicializando el constructor:

class CustomTitle extends HTMLElement { constructor() { super() //... }}

Luego, llamamos al attachShadow()método de HTMLElement pasando un objeto con la modepropiedad establecida en 'open'. Esta propiedad establece el modo de encapsulación para el shadow DOM. Si es , openpodemos acceder a la shadowRootpropiedad de un elemento. Si está cerrado, no podemos.

A continuación te explicamos cómo hacerlo:

class CustomTitle extends HTMLElement { constructor() { super() this.attachShadow({ mode: 'open' }) //... }}

Encontrarás algunos ejemplos que usan la sintaxis const shadowRoot = this.attachShadow(/* ... */)pero puedes evitarlo a menos que lo configures mode, closedya que siempre puedes hacer referencia a ese objeto llamando a this.shadowRoot.

Esto es lo que vamos a hacer ahora para configurar el innerHTML:

class CustomTitle extends HTMLElement { constructor() { super() this.attachShadow({ mode: 'open' }) this.shadowRoot.innerHTML = ` h1My Custom Title!/h1 ` }}

Puedes agregar tantas etiquetas como quieras, no estás limitado a una etiqueta dentro de la innerHTMLpropiedad

Ahora agregamos este elemento recién definido a window.customElements:

window.customElements.define('custom-title', CustomTitle)

¡Y podemos usar el custom-title/custom-titleElemento Personalizado en la página!

Nota: no se pueden utilizar etiquetas de cierre automático (en otras palabras: esto custom-title /no está permitido por el estándar)

Observe el -guion en el nombre de la etiqueta. Debemos usar un guion en un elemento personalizado. Así es como podemos distinguir una etiqueta integrada de una personalizada.

Ahora tenemos este elemento en la página y podemos hacer lo que hacemos con otras etiquetas: ¡orientarlo con CSS y JavaScript!

Proporcionar un CSS personalizado para el elemento

En el constructor, puedes pasar una styleetiqueta además de la etiqueta HTML que define el contenido, y dentro de ella puedes tener el CSS del elemento personalizado:

class CustomTitle extends HTMLElement { constructor() { super() this.attachShadow({ mode: 'open' }) this.shadowRoot.innerHTML = ` style h1 { font-size: 7rem; color: #000; font-family: Helvetica; text-align: center; } /style h1My Custom Title!/h1 ` }}

Aquí está el ejemplo del elemento personalizado que creamos en Codepen: https://codepen.io/flaviocopes/pen/LKgjzK/ Armario escobero

 

Una sintaxis más corta

En lugar de definir primero la clase y luego llamarla, window.customElements.define()también podemos usar esta sintaxis abreviada para definir la clase en línea :

window.customElements.define('custom-title', class extends HTMLElement { constructor() { ... }})

Añadir JavaScript

Al igual que hicimos con CSS, podemos incorporar JavaScript.

Sin embargo, no podemos agregarlo directamente a la etiqueta de plantilla como lo hicimos para CSS.

Aquí defino un detector de eventos de clic en el constructor del elemento personalizado:

class CustomTitle extends HTMLElement { constructor() { super() this.attachShadow({ mode: 'open' }) this.shadowRoot.innerHTML = ` h1My Custom Title!/h1 ` this.addEventListener('click', (e) = { alert('clicked!') }) }}

Alternativa: utilizar plantillas

En lugar de definir el HTML y el CSS en una cadena de JavaScript, puedes usar una templateetiqueta en HTML y asignarle un id:

template style h1 { font-size: 7rem; color: #000; font-family: Helvetica; text-align: center; } /style h1My Custom Title!/h1/templatecustom-title/custom-title

Luego, puedes hacer referencia a él en tu constructor de elementos personalizados y agregarlo al Shadow DOM:

class CustomTitle extends HTMLElement { constructor() { super() this.attachShadow({ mode: 'open' }) const tmpl = document.querySelector('#custom-title-template') this.shadowRoot.appendChild(tmpl.content.cloneNode(true)) }}window.customElements.define('custom-title', CustomTitle)

Ejemplo en Codepen: https://codepen.io/flaviocopes/pen/oramEY/

Ganchos de ciclo de vida

Además de constructor, una clase de elemento personalizado puede definir aquellos métodos especiales que se ejecutan en momentos especiales durante el ciclo de vida del elemento:

  • connectedCallbackcuando el elemento se inserta en el DOM
  • disconnectedCallbackcuando el elemento se elimina del DOM
  • attributeChangedCallbackCuando un atributo observado cambia, se agrega o se elimina
  • adoptedCallbackCuando el elemento se ha movido a un nuevo documento
class CustomTitle extends HTMLElement { constructor() { ... } connectedCallback() { ... } disconnectedCallback() { ... } attributeChangedCallback(attrName, oldVal, newVal) { ... }}

attributeChangedCallback()obtiene 3 parámetros:

  • el nombre del atributo
  • el antiguo valor del atributo
  • el nuevo valor del atributo.

Mencioné que escucha los atributos observados. ¿Cuáles son? Debemos definirlos en una matriz devuelta por el observedAttributesmétodo estático:

 

class CustomTitle extends HTMLElement { constructor() { ... } static get observedAttributes() { return ['disabled'] } attributeChangedCallback(attrName, oldVal, newVal) { ... }}

He definido el disabledatributo que se debe observar. Ahora, cuando cambia, por ejemplo en JavaScript, lo configuramos disabledcomo verdadero:

document.querySelector('custom-title').disabled = true

los attributeChangedCallback()incendios con el conjunto de parámetros 'disabled', false, true.

Nota: attributeChangedCallback()se puede llamar al elemento mediante JavaScript (por algún motivo que desconozco), pero no debería hacerlo. El navegador debería invocarlo automáticamente.

Definir atributos personalizados

Puede definir atributos personalizados para sus elementos personalizados agregando un captador y un definidor para ellos:

class CustomTitle extends HTMLElement { static get observedAttributes() { return ['mycoolattribute'] } get mycoolattribute() { return this.getAttribute('mycoolattribute') } set mycoolattribute(value) { this.setAttribute('mycoolattribute', value) }}

Así es como puedes definir atributos booleanos, que son “verdaderos” si están presentes, como disabledpara los elementos HTML:

class CustomTitle extends HTMLElement { static get observedAttributes() { return ['booleanattribute'] } get booleanattribute() { return this.hasAttribute('booleanattribute') } set booleanattribute(value) { if (value) { this.setAttribute('booleanattribute', '') } else { this.removeAttribute('booleanattribute') } }}

Cómo diseñar un elemento personalizado que aún no está definido

Es posible que JavaScript tarde un poco en activarse y que un elemento personalizado no se defina tan pronto como se cargue la página. La página puede presentar un diseño desagradable cuando se agrega el elemento a la página.

Para resolver este problema, agregue una :not(:defined)pseudoclase CSS que establezca la altura y se desvanezca en el elemento cuando esté disponible:

custom-title:not(:defined) { display: block; height: 400px; opacity: 0; transition: opacity 0.5s ease-in-out;}

¿Puedo usarlos en todos los navegadores?

Las versiones actuales de Firefox, Safari y Chrome son compatibles con ellos, pero IE nunca lo será y, al momento de escribir este artículo, Edge ya tiene soporte para ellos en desarrollo.

Puedes usar este polyfill para agregar un mejor soporte también para navegadores más antiguos.




Tal vez te puede interesar:

  1. Introducción a React
  2. Agregar evento de clic a los elementos DOM devueltos desde querySelectorAll
  3. Cómo cambiar el valor de un nodo DOM
  4. Cómo comprobar si un elemento DOM tiene una clase

Elementos personalizados de componentes web

El CustomElementRegistryobjetoCómo crear un elemento personalizadoProporcionar un CSS personalizado para el elementoUna sintaxis más cortaAñadir JavaScriptA

programar

es

https://aprendeprogramando.es/static/images/programar-elementos-personalizados-de-componentes-web-2091-0.jpg

2024-11-01

 

Elementos personalizados de componentes web 1
Elementos personalizados de componentes web 1

Si crees que alguno de los contenidos (texto, imagenes o multimedia) en esta página infringe tus derechos relativos a propiedad intelectual, marcas registradas o cualquier otro de tus derechos, por favor ponte en contacto con nosotros en el mail [email protected] y retiraremos este contenido inmediatamente

 

 

Update cookies preferences