Por lo tanto, he leído varias piezas que dicen que si desea que un evento personalizado atraviese el límite del DOM de la sombra y cruce el DOM de la luz, debe establecer la propiedad composed
del evento personalizado en verdadero. Sin embargo, noté que cualquier evento que envío desde un componente web es this.
salga bien del componente shadowRoot , y los que se envían desde this.shadowRoot
permanecen dentro. Entonces, ¿por qué necesito la propiedad "compuesta"? ¿Estoy haciendo algo mal?
const internalEvent = new CustomEvent("internalEvent", {bubbles: true, cancelable: false}) const externalEvent = new CustomEvent("externalEvent", {bubbles: true, cancelable: false}) class MyComponent extends HTMLElement { constructor() { super() this.attachShadow({ mode: 'open' }) this.shadowRoot.innerHTML = ` <button id="internalButton">INTERNAL</button> <button id="externalButton">EXTERNAL</button> ` this.internalButton = this.shadowRoot.getElementById("internalButton") this.externalButton = this.shadowRoot.getElementById("externalButton") } connectedCallback() { this.internalButton.addEventListener("click", ()=>{ this.shadowRoot.dispatchEvent(internalEvent) }) this.externalButton.addEventListener("click", ()=>{ this.dispatchEvent(externalEvent) }) this.shadowRoot.addEventListener("internalEvent", (event)=>{ console.log("Internal event detected internally.") }) this.shadowRoot.addEventListener("externalEvent", (event)=>{ console.log("External event detected internally!") }) } } document.addEventListener("internalEvent", ()=>console.log("Internal event detected externally!")) document.addEventListener("externalEvent", ()=>console.log("External event detected externally.")) customElements.define('my-component', MyComponent)
editar: estoy luchando por pensar en alguna razón por la que, para obtener un mensaje para dejar su componente, prefiera enviarlo dentro de shadowRoot y agregar una propiedad especial, en lugar de simplemente enviarlo directamente a la luz DOM en El primer lugar.
Como han mencionado otros, this
no está en la sombra DOM de su componente; es el componente que tiene este shadow DOM.
si puedo despachar
this
, ¿por qué no haría eso en lugar de agregar propiedades adicionales a mi evento?
Todavía no podría pasar ningún límite de shadowDOM circundante posible (su componente web puede ser un elemento secundario o descendiente de otro componente web que utiliza shadow DOM). Esto puede ser deseable o no, dependiendo de dónde desee que el evento sea monitoreable.
También tenga en cuenta que se puede llamar a connectedCallback
varias veces, por ejemplo, si se mueve un elemento en el DOM; asegúrese de remove
siempre cualquier oyente de eventos que haya agregado en la devolución de llamada connectedCallback
en la devolución de disconnectedCallback
, o incluso preferible, agregue los oyentes internos en el constructor
(que se garantiza que solo se ejecutará una vez y le ahorra la molestia de necesitar referencias a los oyentes para poder eliminarlos).
' this ' es el elemento personalizado/componente web <my-component>
,
' esto ' no está dentro de los elementos shadowRoot.
Entonces, los eventos que envías desde ' esto ', no cruzan los límites de shadowDOM.
Solo necesita composed: true
cuando los eventos deben cruzar (también conocido como "escape") shadowDOM –
<script> const EventName = "HelloFromComponent"; customElements.define('my-component', class extends HTMLElement { constructor() { let attach = (btn, composed = false, el = this.shadowRoot.getElementById(btn)) => el.onclick = () => { el.dispatchEvent(new CustomEvent(EventName, { bubbles: true, cancelable: false, composed: composed })) } super().attachShadow({mode: 'open'}) .innerHTML = `<button id="one">One</button><button id="two">Two</button>`; attach("one", /* composed = */ false ); attach("two", /* composed = */ true ); } listen(where) { where.addEventListener(EventName, (evt) => { console.log(where.nodeName, evt.type, evt.composed, ); }) } connectedCallback() { this.listen(this); this.listen(document); } }); </script> <my-component></my-component>
Me acabo de dar cuenta de que una de las razones (tal vez la razón) sería si desea que el evento se capture tanto dentro como fuera de su componente. Sin la propiedad de compose
, necesitaría emitir dos eventos separados.