--- title: Custom Elements slug: Web/Web_Components/Custom_Elements tags: - Componentes Web - Web Components - custom elements translation_of: Web/Web_Components/Using_custom_elements translation_of_original: Web/Web_Components/Custom_Elements ---

Los Custom Elements son una característica que permite crear tus propios elementos HTML personalizados. Pueden tener un comportamiento personalizado y estilos CSS propios. Son una parte de los Web Components, pero también pueden ser utilizados independientemente.

Nota: Los Custom elements sólo se han estabilizado recientemente, y partes de MDN todavía contienen información desactualizada de las APIs de los antiguos borradores de la especificación.

Puede no estar claro por qué se creó la nueva capacidad de elementos personalizados, ya que ya era posible crear una etiqueta como <mytag> y aplicarle estilo con CSS, luego utilizar scripts para darle comportamiento. Una ventaja que tienen los custom elements son las reacciones de ciclo de vida (lifecycle reactions), que permiten asociar comportamiento a diferentes partes del nuevo "ciclo de vida" del elemento. Por ejemplo, se puede asociar un comportamiento concreto cuando un nuevo elemento se inserta en el DOM ("conectado"), y otro distinto cuando es eliminado del DOM ("desconectado"), o cuando sus atributos cambien.

El habilitador de claves de los elementos personalizados v1 es el método {{domxref("CustomElementRegistry.define()")}}, el cual se puede utilizar para definir un nuevo elemento personalizado. El nuevo elemento utilizará la clase suministrada para cualquier instancia, en lugar del valor predeterminado  {{domxref("HTMLUnknownElement")}}.  Los elementos personalizados pueden basarse en un elemento nativo como <button>,  utilizando la sintaxis  <button is="my-button">;  estos se llaman elementos integrados personalizados.

Métodos de custom element

Los Custom elements tienen los siguientes métodos que dictan su comportamiento:

constructor()
Llamado cuando el elemento es creado o actualizado
connectedCallback()
Llamado cuando el elemento se es insertado en el documento, incluyéndose en un árbol shadow
disconnectedCallback()
Llamado cuando el elemento es eliminado de un documento
attributeChangedCallback(nombreDelAtributo, antiguoValor, nuevoValor, dominio)
Llamado cuando un atributo es cambiado, concatenado, eliminado o reemplazado en el elemento. Sólo llamado sobre atributos observados.
adoptedCallback(antiguoDocumento, nuevoDocumento)
Llamado cuando un elemento es adoptado en otro nuevo documento

Ejemplo

Los custom elements necesitan usar la sintaxis de clase introducida en las versiones modernas de JavaScript.

Archivo HTML:

Si no aparece nada debajo, es que tu navegador no soporta aún los Custom Elements.
<x-product data-name="Ruby" data-img="https://s3-us-west-2.amazonaws.com/s.cdpn.io/4621/ruby.png" data-url="http://example.com/1"></x-product>
<x-product data-name="JavaScript" data-img="https://s3-us-west-2.amazonaws.com/s.cdpn.io/4621/javascript.png" data-url="http://example.com/2"></x-product>
<x-product data-name="Python" data-img="https://s3-us-west-2.amazonaws.com/s.cdpn.io/4621/python.png" data-url="http://example.com/3"></x-product>

Archivo JS:

// Declaración de un custom element que hereda de HTMLElement
class XProduct extends HTMLElement {
  constructor() {
    // Siempre debe llamarse primero al constructor padre
    super();

    // Se crea el shadow root
    var shadow = this.attachShadow({mode: 'open'});

    // Se crea un elemnto img y se asignan sus atributos.
    var img = document.createElement('img');
    img.alt = this.getAttribute('data-name');
    img.src = this.getAttribute('data-img');
    img.width = '150';
    img.height = '150';
    img.className = 'product-img';

    // Añadir la imagen al shadow root.
    shadow.appendChild(img);

    // Añadir un elemento de escucha a la imagen.
    img.addEventListener('click', () => {
      window.location = this.getAttribute('data-url');
    });

    // Crear un enlace al producto.
    var link = document.createElement('a');
    link.innerText = this.getAttribute('data-name');
    link.href = this.getAttribute('data-url');
    link.className = 'product-name';

    // Añadir el enlace al shadow root.
    shadow.appendChild(link);
  }
}

// Definir el nuevo elemento.
customElements.define('x-product', XProduct);

Archivo CSS:

body {
  background: #F7F7F7;
}

x-product {
  display: inline-block;
  float: left;
  margin: 0.5em;
  border-radius: 3px;
  background: #FFF;
  box-shadow: 0 1px 3px rgba(0,0,0,0.25);
  font-family: Helvetica, arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}

x-product::slotted(.product-img) {
  cursor: pointer;
  background: #FFF;
  margin: 0.5em;
}

x-product::slotted(.product-name) {
  display: block;
  text-align: center;
  text-decoration: none;
  color: #08C;
  border-top: 1px solid #EEE;
  font-weight: bold;
  padding: 0.75em 0;
}

A continuación se muestra el ejemplo en vivo de lo anterior:

{{ EmbedLiveSample('Example', '1500', '250', '', 'Web/Web_Components/Custom_Elements') }}

Atributos Observados

Para ser notificado cuando un atributo cambia, se debe definir una lista de atributos observados al inicializar el elemento, poniendo un getter estático observedAttributes en la clase del elemento que devuelve un array de nombre de atributos.

Archivo JS:

class HelloElement extends HTMLElement {
  // Observar los cambios en el atributo 'name'.
  static get observedAttributes() {return ['name']; }

  // Responder a los cambios en el atributo.
  attributeChangedCallback(attr, oldValue, newValue) {
    if (attr == 'name') {
      this.textContent = `Hello, ${newValue}`;
    }
  }
}

// Definir el nuevo elemento
customElements.define('hello-element', HelloElement);

Archivo HTML:

<hello-element name="Anita"></hello-element>

A continuación está el ejemplo en vivo de lo anterior:

{{ EmbedLiveSample('Observed_attributes', '750', '100', '', 'Web/Web_Components/Custom_Elements') }}

Especificaciones

Los Custom Elements están definido en la siguiente especificación:

Especificación Estado Comentario
The HTML Standard: Custom elements LS  

Recursos