Доступ к дочерним узлам пользовательских элементов?

Это может быть немного запутанным. Я пытаюсь получить доступ к innerHTML или childNodes из моего пользовательского элемента. Можно ли получить доступ к исходной структуре DOM из файла импорта веб-компонента? ДО прикрепить тень?

В приведенном ниже примере я пытаюсь получить доступ к src двух изображений jookah из моего файла импорта jookah-gallery.

Отказ от ответственности: я абсолютный нуб, когда дело доходит до теневого DOM и веб-компонентов, поэтому, если есть какие-то серьезные ошибки, я бы хотел понять, почему. Спасибо за любую помощь!

index.html

<jookah-gallery>
    //here
    <jookah-image class="gallery-image" src="http://merehead.com/blog/wp-content/uploads/gradient-design.jpeg">
    <jookah-image class="gallery-image" src="https://webgradients.com/public/webgradients_png/035%20Itmeo%20Branding.png">
</jookah-gallery>

Импортировать файл для галереи Jookah:

(function(owner) {

    class jookahGallery extends HTMLElement {

        constructor() {

            super();

            //this returns false
            if (this.hasChildNodes()) {
                console.log('there are nodes')
            }else{
                console.log('NO nodes')
            }

            //shadow DOM attach
            const shadowRoot = this.attachShadow({mode: 'open'});
            const template = owner.querySelector('#jookah-gallery-template');
            const instance = template.content.cloneNode(true);
            shadowRoot.appendChild(instance);


        }

        // ---------------- object events -------------------------//

        connectedCallback() {
        }

        render(){
        }

        disconnectedCallback(){
        }

        attributeChangedCallback(){
        }

        // ---------------- methods ------------------------//


    }

    customElements.define('jookah-gallery', jookahGallery);

})(document.currentScript.ownerDocument);

1 ответ

Решение

Согласно спецификации вы не должны проверять, изменять, добавлять и дочерние элементы в конструкторе вашего веб-компонента.

https://w3c.github.io/webcomponents/spec/custom/

Вместо этого вам нужно переместить чтение детей в ваш связанный обратный вызов:

class jookahGallery extends HTMLElement {
  constructor() {
    super();
    this._childrenRead = false;

    const shadowRoot = this.attachShadow({mode: 'open'});
    const template = document.createElement('template');
    template.innerHtml = `Place your template here`;
    const instance = template.content.cloneNode(true);
    shadowRoot.appendChild(instance);
  }

  connectedCallback() {
    if (!this._childrenRead) {
      this._childrenRead = true;

      if (this.hasChildNodes()) {
          console.log('there are nodes')
      }else{
          console.log('NO nodes')
      }
    }
  }
}

customElements.define('jookah-gallery', jookahGallery);

Вы также можете использовать<slot> встраивать своих детей. Но есть некоторые проблемы с CSS, которые необходимо учитывать при использовании слотов.

Помните, что shadowDOM поддерживается не во всех браузерах и не является простым полифилом. Так что, если вы работаете только с Chrome и Safari, сделайте это. Если вы планируете поддерживать более широкий диапазон браузеров, то вы, возможно, пока не захотите использовать ShadowDOM.

https://alligator.io/web-components/composing-slots-named-slots/

Также читайте больше здесь: Как использовать дочерние элементы в веб-компонентах

Другие вопросы по тегам