1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
|
---
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
---
<p>Los <em>Custom Elements </em>son una característica que permite crear tus propios <a href="https://developer.mozilla.org/en-US/docs/Glossary/Element">elementos</a> HTML personalizados. Pueden tener un comportamiento personalizado y estilos CSS propios. Son una parte de los <a href="https://developer.mozilla.org/en-US/docs/Web/Web_Components">Web Components</a>, pero también pueden ser utilizados independientemente.</p>
<div class="note">
<p><strong>Nota:</strong> Los <em>Custom elements</em> 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.</p>
</div>
<p>Puede no estar claro por qué se creó la nueva capacidad de elementos personalizados, ya que ya era posible crear una etiqueta como <code><mytag></code> y aplicarle estilo con CSS, luego utilizar scripts para darle comportamiento. Una ventaja que tienen los <em>custom elements</em> son las reacciones de ciclo de vida (<em>lifecycle reactions)</em>, 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.</p>
<p>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 <code><button></code>, utilizando la sintaxis <code><button is="my-button"></code>; estos se llaman <em>elementos integrados personalizados.</em></p>
<h2 id="Métodos_de_custom_element">Métodos de <em>custom element</em></h2>
<p>Los <em>Custom elements</em> tienen los siguientes métodos que dictan su comportamiento:</p>
<dl>
<dt>constructor()</dt>
<dd>Llamado cuando el elemento es creado o actualizado</dd>
<dt>connectedCallback()</dt>
<dd>Llamado cuando el elemento se es insertado en el documento, incluyéndose en un árbol shadow</dd>
<dt>disconnectedCallback()</dt>
<dd>Llamado cuando el elemento es eliminado de un documento</dd>
<dt>attributeChangedCallback(nombreDelAtributo, antiguoValor, nuevoValor, dominio)</dt>
<dd>Llamado cuando un atributo es cambiado, concatenado, eliminado o reemplazado en el elemento. Sólo llamado sobre <a href="#Atributos_Observados">atributos observados</a>.</dd>
<dt>adoptedCallback(antiguoDocumento, nuevoDocumento)</dt>
<dd>Llamado cuando un elemento es adoptado en otro nuevo documento</dd>
</dl>
<h2 id="Ejemplo">Ejemplo</h2>
<p>Los <em>custom elements</em> necesitan usar la <a href="https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Classes">sintaxis de clase</a> introducida en las versiones modernas de JavaScript.</p>
<p>Archivo HTML:</p>
<pre class="brush: 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></pre>
<p>Archivo JS:</p>
<pre class="brush: js">// Declaración de un <em>custom element</em> que hereda de HTMLElement
class XProduct extends HTMLElement {
constructor() {
// Siempre debe llamarse primero al constructor padre
super();
// Se crea el <em>shadow root</em>
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);
</pre>
<p>Archivo CSS:</p>
<pre class="brush: 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;
}
</pre>
<p>A continuación se muestra el ejemplo en vivo de lo anterior:</p>
<p>{{ EmbedLiveSample('Example', '1500', '250', '', 'Web/Web_Components/Custom_Elements') }}</p>
<h2 id="Atributos_Observados">Atributos Observados</h2>
<p>Para ser notificado cuando un atributo cambia, se debe definir una lista de atributos observados al inicializar el elemento, poniendo un getter estático <code>observedAttributes</code> en la clase del elemento que devuelve un array de nombre de atributos.</p>
<p>Archivo JS:</p>
<pre class="brush: 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);
</pre>
<p>Archivo HTML:</p>
<pre class="brush: html"><hello-element name="Anita"></hello-element></pre>
<p>A continuación está el ejemplo en vivo de lo anterior:</p>
<p>{{ EmbedLiveSample('Observed_attributes', '750', '100', '', 'Web/Web_Components/Custom_Elements') }}</p>
<h2 id="Especificaciones">Especificaciones</h2>
<p>Los <em>Custom Elements </em>están definido en la siguiente especificación:</p>
<table class="spec-table standard-table">
<tbody>
<tr>
<th scope="col">Especificación</th>
<th scope="col">Estado</th>
<th scope="col">Comentario</th>
</tr>
<tr>
<td><a href="https://html.spec.whatwg.org/multipage/scripting.html#custom-elements">The HTML Standard: Custom elements</a></td>
<td>LS</td>
<td> </td>
</tr>
</tbody>
</table>
<h2 id="Recursos">Recursos</h2>
<ul>
<li><a href="https://developers.google.com/web/fundamentals/primers/customelements/">Custom elements v1: reusable web components - Google Developers tutorial</a></li>
</ul>
|