You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: 8-web-components/2-custom-elements/article.md
+24-24Lines changed: 24 additions & 24 deletions
Original file line number
Diff line number
Diff line change
@@ -3,7 +3,7 @@
3
3
4
4
Podemos crear elementos HTML personalizados, descritos por nuestra clase, con sus propios métodos, propiedades, eventos y demás.
5
5
6
-
Una vez que el elemento personalizado es definido, podemos usarlo a la par con los elementos HTML nativos.
6
+
Una vez que el elemento personalizado es definido, podemos usarlo a la par de elementos HTML nativos.
7
7
8
8
Esto es grandioso, porque el el diccionario HTML es rico pero no infinito. No hay `<aletas-faciles>`, `<gira-carrusel>`, `<bella-descarga>`... Solo piensa en cualquier otra etiqueta que puedas necesitar.
9
9
@@ -12,7 +12,7 @@ Podemos definirlos con una clase especial, y luego usarlos como si siempre hubie
12
12
Hay dos clases de elementos personalizados:
13
13
14
14
1.**Elementos personalizados autónomos** -- elementos "todo-nuevo", extendiendo la clase abstracta `HTMLElement`.
15
-
2.**Elementos incorporados personalizados** -- extendiendo elementos incorporados, como un botón personalizado basado en `HTMLButtonElement`, etc.
15
+
2.**Elementos incorporados personalizados** -- extendiendo elementos nativos, por ejemplo un botón personalizado basado en `HTMLButtonElement`.
16
16
17
17
Primero cubriremos los elementos autónomos, luego pasaremos a la personalización de elementos nativos.
18
18
@@ -31,24 +31,24 @@ class MyElement extends HTMLElement {
31
31
32
32
connectedCallback() {
33
33
// el navegador llama a este método cuando el elemento es agregado al documento
34
-
// (puede ser llamado varias veces si un elemento es agregado/quitado repetidamente)
34
+
// (puede ser llamado varias veces si un elemento es agregado y quitado repetidamente)
35
35
}
36
36
37
37
disconnectedCallback() {
38
38
// el navegador llama a este método cuando el elemento es quitado del documento
39
-
// (puede ser llamado varias veces si un elemento es agregado/quitado repetidamente)
39
+
// (puede ser llamado varias veces si un elemento es agregado y quitado repetidamente)
40
40
}
41
41
42
42
staticgetobservedAttributes() {
43
43
return [/* array de nombres de atributos para monitorear cambios */];
// llamado cuando uno de los atributos listados arriba es modificado
47
+
//es llamado cuando uno de los atributos listados arriba es modificado
48
48
}
49
49
50
50
adoptedCallback() {
51
-
// llamado cuando el elemento es movido a un nuevo documento
51
+
//es llamado cuando el elemento es movido a un nuevo documento
52
52
// (ocurre en document.adoptNode, muy raramente usado)
53
53
}
54
54
@@ -63,19 +63,19 @@ Después de ello, necesitamos registrar el elemento:
63
63
customElements.define("my-element", MyElement);
64
64
```
65
65
66
-
A partir de ello, para cada elemento HTML con la etiqueta `<my-element>` se crea una instancia de `MyElement` y los métodos mencionados son llamados. También podemos crearlo con JavaScript: `document.createElement('my-element')`.
66
+
A partir de ello, para cada elemento HTML con la etiqueta `<my-element>` se crea una instancia de `MyElement` y los métodos mencionados son llamados. También podemos insertarlo con JavaScript: `document.createElement('my-element')`.
67
67
68
68
```smart header="Los elementos personalizados deben incluir un guion `-`"
69
69
Los elemento personalizados deben incluir un guion corto `-`. Por ejemplo, `my-element` y `super-button` son nombres válidos, pero `myelement` no lo es.
70
70
71
-
Esto es para asegurar que no hay conflicto de nombres entre los elementos nativos y los personalizados.
71
+
Esto es para asegurar que no haya conflicto de nombres entre los elementos nativos y los personalizados.
72
72
```
73
73
74
74
## Ejemplo: "time-formatted"
75
75
76
-
Por ejemplo, ya existe un elemento `<time>` en HTML para presentar fecha y hora, pero no hace ningún formateo por sí mismo.
76
+
Ejemplo: ya existe un elemento `<time>` en HTML para presentar fecha y hora, pero no hace ningún formateo por sí mismo.
77
77
78
-
Construyamos el elemento `<time-formatted>` que muestre la hora en un bonito formato que reconozca la lengua:
78
+
Construyamos el elemento `<time-formatted>` que muestre la hora en un bonito formato y reconozca la configuración de lengua local:
1. La clase tiene un solo método, `connectedCallback()`, que es llamado por el navegador cuando se agrega el elemento `<time-formatted>` a la página (o cuando el analizador "parser" HTML lo detecta). Este método usa el formateador de datos nativo [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat), bien soportado por los navegadores, para mostrar una agradable hora formateada.
118
+
1. La clase tiene un solo método, `connectedCallback()`, que es llamado por el navegador cuando se agrega el elemento `<time-formatted>` a la página (o cuando el analizador HTML lo detecta). Este método usa el formateador de datos nativo [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat), bien soportado por los navegadores, para mostrar una agradable hora formateada.
119
119
2. Necesitamos registrar nuestro nuevo elemento con `customElements.define(tag, class)`.
120
-
3. Y ya podemos usarlo por doquier.
120
+
3. Y podremos usarlo por doquier.
121
121
122
122
123
123
```smart header="Actualización de elementos personalizados"
124
124
Si el navegador encuentra algún `<time-formatted>` antes de `customElements.define`, no es un error. Pero el elemento es todavía desconocido, como cualquier etiqueta no estándar.
125
125
126
126
Tal elemento "undefined" puede ser estilizado con el selector CSS `:not(:defined)`.
127
127
128
-
Una vez que `customElement.define` es llamado, tales elementos son "actualizados": una nueva instancia de `TimeFormatted`
129
-
es creada para cada uno y `connectedCallback` es llamado. Se vuelven `:defined`.
128
+
Una vez que `customElement.define` es llamado, estos elementos son "actualizados": para cada elemento, una nueva instancia de `TimeFormatted`
129
+
es creada y `connectedCallback` es llamado. Se vuelven `:defined`.
130
130
131
131
Para obtener información acerca los elementos personalizados, tenemos los métodos:
132
132
- `customElements.get(name)` -- devuelve la clase del elemento personalizado con el `name` dado,
133
133
- `customElements.whenDefined(name)` -- devuelve una promesa que se resuelve (sin valor) cuando un elemento personalizado con el `name` dado se vuelve `defined`.
134
134
```
135
135
136
136
```smart header="Renderizado en `connectedCallback`, no en el `constructor`"
137
-
En el ejemplo de arriba, el contenido del elemento es renderizado (creado) en `connectedCallback`.
137
+
En el ejemplo de arriba, el contenido del elemento es renderizado (construido) en `connectedCallback`.
138
138
139
139
¿Por qué no en el `constructor`?
140
140
141
141
La razón es simple: cuando el `constructor` es llamado, es aún demasiado pronto. El elemento es creado, pero el navegador aún no procesó ni asignó atributos en este estado, las llamadas a `getAttribute` devolverían `null`. Así que no podemos renderizar ahora.
142
142
143
143
Por otra parte, si lo piensas, es más adecuado en términos de performance: demorar el trabajo hasta que realmente se lo necesite.
144
144
145
-
El `connectedCallback` se dispara cuando el elemento es agregado al documento. No apenas agregado a otro elemento como hijo, sino cuando realmente se vuelve parte de la página. Así podemos construir un DOM separado, crear elementos y prepararlos para uso futuro. Ellos serán realmente renderizados cuando estén dentro de la página.
145
+
El `connectedCallback` se dispara cuando el elemento es agregado al documento. No apenas agregado a otro elemento como hijo, sino cuando realmente se vuelve parte de la página. Así podemos construir un DOM separado, crear elementos y prepararlos para uso futuro. Ellos serán realmente renderizados una vez que estén dentro de la página.
146
146
```
147
147
148
148
## Observando atributos
149
149
150
-
En la implementación actual de `<time-formatted>`, después de que el elemento fue renderizado, cambios posteriores en sus atributos no tendrán ningún efecto. Eso es extraño para un elemento HTML, porque cuando cambiamos un atributo, como en `a.href`, esperamos que dicho cambio sea visible de inmediato. Corrijamos esto.
150
+
En la implementación actual de `<time-formatted>`, después de que el elemento fue renderizado, cambios posteriores en sus atributos no tendrán ningún efecto. Eso es extraño para un elemento HTML, porque cuando cambiamos un atributo (como en `a.href`) esperamos que dicho cambio sea visible de inmediato. Corrijamos esto.
151
151
152
-
Podemos observar atributos suministrando la lista de ellos al getter estático `observedAttributes()`. Cuando tales atributos son modificados, se dispara `attributeChangedCallback`. No se dispara para los atributos no incluidos en la lista, por razones de performance.
152
+
Podemos observar atributos suministrando la lista de ellos al getter estático `observedAttributes()`. Cuando esos atributos son modificados, se dispara `attributeChangedCallback`. No se dispara para los atributos no incluidos en la lista, por razones de performance.
153
153
154
154
A continuación, el nuevo `<time-formatted>` que se actualiza con el cambio de atributos:
2. Lo llamamos una vez cuando el elemento es insertado en la página.
213
213
3. Al cambiar un atributo listado en `observedAttributes()`, se dispara `attributeChangedCallback`.
214
214
4. ...y se re-renderiza el elemento.
215
-
5. Como resultado, fácilmente podemos hacer un reloj dinámico.
215
+
5. Como resultado, ahora podemos crear un reloj dinámico con facilidad.
216
216
217
217
## Orden de renderizado
218
218
@@ -242,7 +242,7 @@ customElements.define('user-info', class extends HTMLElement {
242
242
243
243
Si lo ejecutas, el `alert` está vacío.
244
244
245
-
Esto es porque no hay hijos en aquel estadio, pues el DOM no está finalizado. Se conectó el elemento personalizado `<user-info>` y está por proceder con sus hijos, pero no lo hizo aún.
245
+
Esto es porque no hay hijos en aquel estadio, pues el DOM no está finalizado. Se conectó el elemento personalizado `<user-info>` y está por proceder con sus hijos, pero no lo hizo aún.
246
246
247
247
Si queremos pasar información al elemento personalizado, podemos usar atributos. Estos están disponibles inmediatamente.
248
248
@@ -272,7 +272,7 @@ Ahora el `alert` en la línea `(*)` muestra "John" porque lo corremos asincróni
272
272
273
273
Por otro lado, la solución tampoco es perfecta. Si los elementos anidados también usan `setTimeout` para inicializarse, entonces van a la cola: el `setTimeout` externo se dispara primero y luego el interno.
274
274
275
-
Entonces el elemento externo termina la inicialización antes que el interno.
275
+
Como consecuencia, el elemento externo termina la inicialización antes que el interno.
276
276
277
277
Demostrémoslo con un ejemplo:
278
278
@@ -302,7 +302,7 @@ Orden de salida:
302
302
303
303
Claramente vemos que el elemento finaliza su inicialización `(3)` antes que el interno `(4)`.
304
304
305
-
No existe un callback nativo que se dispare después de que los elementos anidados estén listos. Si es necesario, podemos implementarlo nosotros mismos. Por ejemplo, elementos internos pueden disparar eventos como `initialized`, y los externos escucharlos para reaccionar a ellos.
305
+
No existe un callback nativo que se dispare después de que los elementos anidados estén listos. Si es necesario, podemos implementarlo nosotros mismos. Por ejemplo, elementos internos pueden disparar eventos como `initialized`, y los externos pueden escucharlos para reaccionar a ellos.
306
306
307
307
## Elementos nativos personalizados
308
308
@@ -320,7 +320,7 @@ Por ejemplo, los botones son instancias de `HTMLButtonElement`, construyamos sob
320
320
classHelloButtonextendsHTMLButtonElement { /* métodos de elemento personalizado */ }
321
321
```
322
322
323
-
2. Ponemos el tercer argumento de `customElements.define`, que especifica la etiqueta:
323
+
2. Ponemos el tercer argumento de `customElements.define`, el cual especifica la etiqueta:
0 commit comments