- Notifications
You must be signed in to change notification settings - Fork230
Shadow DOM and events#550
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Changes fromall commits
0c8ccfc10523a94d9df720dc173a3ca282bFile filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,14 +1,14 @@ | ||
| # Shadow DOMy eventos | ||
| La ideadetrás delshadow treees encapsular los detalles internos de implementación de un componente. | ||
| Digamos que ocurre un evento click dentro de unshadow DOMdel componente`<user-card>`. Pero losscriptsen el documento principalnotienenideaacerca del interior delshadow DOM, especialmente si el componente es de una librería de terceros. | ||
| Entonces, para mantener los detalles encapsulados, el navegador *redirige* el evento. | ||
| **Los eventos que ocurren en elshadow DOMtienen el elementohostcomo objetivo cuando son atrapados fuera del componente.** | ||
| Un ejemplo simple: | ||
| ```html run autorun="no-epub" untrusted height=60 | ||
| <user-card></user-card> | ||
| @@ -30,16 +30,16 @@ document.onclick = | ||
| </script> | ||
| ``` | ||
| Si haces clic en el botón, los mensajes son: | ||
| 1. Inner target: `BUTTON` --el manejador de evento interno obtiene el objetivo correcto, el elemento dentro del shadow DOM. | ||
| 2. Outer target: `USER-CARD` --el manejador de evento del documento obtiene elshadow hostcomo objetivo. | ||
| Tener la "redirección de eventos" es muy bueno, porque el documento externo no necesita tener conocimiento acerca del interior del componente. Desde su punto de vista, el evento ocurrió sobre `<user-card>`. | ||
| **No hay redirección si el evento ocurre en un elemento eslotado (slotelement), que físicamente se aloja en el "light DOM", el DOM visible.** | ||
| Por ejemplo, si un usuario hace clic en`<span slot="username">`en el ejemplo siguiente, el objetivo del evento es precisamente ese elemento`span`para ambos manejadores, shadowy light. | ||
| ```html run autorun="no-epub" untrusted height=60 | ||
| <user-card id="userCard"> | ||
| @@ -65,19 +65,19 @@ userCard.onclick = e => alert(`Outer target: ${e.target.tagName}`); | ||
| </script> | ||
| ``` | ||
| Si un clic ocurre en `"John Smith"`,eltargetes `<span slot="username">` para ambos manejadores: el interno y el externo. Es un elemento dellight DOM,entonces nohay redirección. | ||
| Por otro lado, si el clic ocurre en un elemento originalmente del shadow DOM,ej. en `<b>Name</b>`,entonces, como se propaga hacia fuera del shadow DOM,su `event.target`se reestablece a `<user-card>`. | ||
| ##Propagación, event.composedPath() | ||
MemberAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. es correcto, Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. @joaquinelio yo creo que lo dejamos como Propagación | ||
| Para el propósito de propagación de eventos, es usado un "flattened DOM" (DOM aplanado, fusión de light y shadow). | ||
| Así, si tenemos un elemento eslotado y un evento ocurre dentro, entonces se propaga hacia arriba a `<slot>`y más allá. | ||
| La ruta completa del destino original"event target", con todos sus elementos shadow, puede ser obtenida usando `event.composedPath()`.Como podemos ver del nombre del método, la ruta se toma despúes de la composición. | ||
| En el ejemplo de arriba, el "flattened DOM" es: | ||
| ```html | ||
| <user-card id="userCard"> | ||
| @@ -92,45 +92,45 @@ In the example above, the flattened DOM is: | ||
| ``` | ||
| Entonces, para un clic sobre `<span slot="username">`,una llamada a `event.composedPath()`devuelve un array: [`span`, `slot`, `div`, `shadow-root`, `user-card`, `body`, `html`, `document`, `window`].Que es precisamente la cadena de padres desde el elemento target en elflattened DOM,después de la composición. | ||
| ```warn header="Los detalles del árbolShadowsolo son provistos en árboles con `{mode:'open'}`" | ||
| Si el árbolshadowfue creado con`{mode: 'closed'}`,la ruta compuesta comienza desde elhost: `user-card`en adelante. | ||
| Este principio essimilara otros métodos que trabajan con elshadow DOM.El interior de árboles cerrados está completamente oculto. | ||
| ``` | ||
| ## event.composed | ||
| La mayoría de los eventos se propagan exitosamente a través de los límites de unshadow DOM. Hay unos pocos eventos que no. | ||
| Esto está gobernado por la propiedad`composed`del objeto de evento. Si es `true`,el evento cruza los límites. Si no, solamente puede ser capturado dentro del shadow DOM. | ||
| Vemos en la [especificaciónUI Events](https://www.w3.org/TR/uievents) que la mayoría de los eventos tienen `composed: true`: | ||
| - `blur`, `focus`, `focusin`, `focusout`, | ||
| - `click`, `dblclick`, | ||
| - `mousedown`, `mouseup` `mousemove`, `mouseout`, `mouseover`, | ||
| - `wheel`, | ||
| - `beforeinput`, `input`, `keydown`, `keyup`. | ||
| Todos los eventos de toque y puntero también tienen `composed: true`. | ||
| Algunos eventos tienen`composed: false`: | ||
| - `mouseenter`, `mouseleave` (que no se propagan en absoluto), | ||
| - `load`, `unload`, `abort`, `error`, | ||
| - `select`, | ||
| - `slotchange`. | ||
| Estos eventos solo pueden ser capturados dentro del mismoDOM,donde reside el evento target. | ||
| ##Eventos personalizados | ||
| Cuando enviamos eventos personalizados, necesitamos establecer ambas propiedades`bubbles`y `composed`a`true`para que se propague hacia arriba y afuera del componente. | ||
| Por ejemplo, aquí creamos`div#inner`en el shadow DOMde `div#outer`y disparamos dos eventos en él. Solo el que tiene `composed: true`logra salir hacia el documento: | ||
| ```html run untrusted height=0 | ||
| <div id="outer"></div> | ||
| @@ -167,26 +167,26 @@ inner.dispatchEvent(new CustomEvent('test', { | ||
| </script> | ||
| ``` | ||
| ##Resumen | ||
| Los eventos solo cruzan los límites deshadow DOMsi su bandera `composed`se establece como `true`. | ||
| La mayoría de los eventos nativos tienen`composed: true`,tal como se describe en las especificaciones relevantes: | ||
| -Eventos UI <https://www.w3.org/TR/uievents>. | ||
| -EventosTouch <https://w3c.github.io/touch-events>. | ||
| -Eventos Pointer <https://www.w3.org/TR/pointerevents>. | ||
| - ...y así. | ||
| Algunos eventos nativos que tienen `composed: false`: | ||
| - `mouseenter`, `mouseleave` (que tampoco se propagan), | ||
| - `load`, `unload`, `abort`, `error`, | ||
| - `select`, | ||
| - `slotchange`. | ||
| Estos eventos solo pueden ser capturados en elementos dentro del mismo DOM. | ||
| Si enviamos un evento personalizado`CustomEvent`,debemos establecer explícitamente `composed: true`. | ||
| Tenga en cuenta que en caso de componentes anidados, un shadow DOMpuede estar anidado dentro de otro. En ese caso los eventos se propagan a través de los límites de todos losshadow DOM. Entonces, si se pretende que un evento sea solo para el componente inmediato que lo encierra, podemos enviarlo también en elshadow hosty establecer `composed: false`.Entonces saldrá alshadow DOM del componente, pero no se propagará hacia un DOM de mayor nivel. | ||