EDITAR He omitido algunos detalles en esta pregunta, pero suponga que ambos elementos ya están definidos . Además, en el problema del mundo real, el árbol DOM es más grande y el componente secundario se inserta en el principal. No hay problema con encontrar el componente secundario.
Tengo dos componentes web: Parent e Child .
Podría usar estos componentes en un marcado como este:
<parent-element> <child-element></child-element> </parent-element> El componente Child tiene la lógica que quiero exponer al padre.
class Child extends HTMLElement { constructor() { ... } publicMethod() { console.log('call me from the parent component'); } }Idealmente, me gustaría llamar al método hijo desde el padre de esta manera:
class Parent extends HTMLElement { constructor() { ... } someTrigger() { const child = this.shadowRoot.querySelector('child-element'); child.publicMethod(); } } Sin embargo, esto no funciona, ya que child es un HTMLElement , porque la API querySelector() devuelve un HTMLElement y no la instancia del componente web.
¿Hay alguna manera de obtener la instancia del componente de manera similar? Me gustaría poder atravesar el árbol de Parent de los componentes principales para encontrar una instancia de componente específica.
Tenga cuidado con whenDefined ;
le dice que se definió el componente web, NO cuando se analizó en el DOM:
Mientras mantenga el <child-element> en lightDOM , <slot> y shadowDOM no tienen nada que ver con ellos.
.as-console-wrapper {max-height:100%!important;top:0;zoom:.88} .as-console-row:nth-child(n-6) {background:#0057B7!important;color:#FFD500!important} .as-console-row:nth-child(n+6) {background:#FFD500!important;color:#0057B7!important} .as-console-row-code{padding:0!important} <script> console.clear(); class Component extends HTMLElement { constructor() { super(); console.log(this.nodeName, "constructor") } connectedCallback(){ console.log("connectedCallback", this.nodeName, this.children.length, "children"); } } customElements.define("child-component", class extends Component { foo() { console.log("Executed <child-element>.foo()"); } }); customElements.define("parent-component", class extends Component { connectedCallback() { super.connectedCallback(); customElements.whenDefined('child-component') .then(() => console.log("Promise resolved, <child-component> IS defined!")); setTimeout(() => { // wait till lightDOM is parsed console.log("After setTimeout",this.nodeName,"has", this.children.length, "children"); this.querySelectorAll("child-component").forEach(child => child.foo()); }) } }) </script> <parent-component> <child-component></child-component> <child-component></child-component> </parent-component>