Предоставьте доступ к элементу веб-компонента из ShadowDom для внешнего JS, используя document.getElementById

Я работаю с текущим шаблоном стартового комплекта PWA от Polymer.

https://github.com/Polymer/pwa-starter-kit/tree/template-typescript

Моя страница элемента веб-компонента возвращает следующий код с элементом DIV:

return html`
      ${SharedStyles}    
      <section>
        ...my content...

      </section>
      <div id="CONTAINER NAME"></div>
    `

Мне нужно получить доступ к элементу ИМЯ КОНТЕЙНЕРА из внешнего javascript через document.getElementById. Я знаю, что он сидит в тени, но я не могу изменить внешний JS. Итак, вопрос в том, как сделать его доступным из JS через document.getElementById?

Внешний JavaScript загружает iframe в названный div, Этот внешний компонент должен получить элемент div document.getElementById загрузить iframe в указанный div.

Я искал и не нашел способа заставить элемент div из теневого домена моей страницы веб-компонента быть выставленным / помещенным в DOM.

Я только что нашел это решение, упомянутое здесь, но я не заставил его работать в шаблоне PWA. Может быть, так как теневые домики каскадируются в шаблоне PWA?

/questions/37968122/predostavte-konkretnyij-element-v-shadowdom-dlya-vneshnego-js-ispolzuya-documentgetelementbyid/37968125#37968125

Можно ли каким-либо образом обновить веб-компонент на основе набора Polymer v3/PWA с помощью внешнего javascript (стороннего производителя), все еще использующего document.getElementbyId для изменения моего div внутри веб-компонента?

Так что в поисках возможности использования возможно slots выставить элемент теневого света на светлый дом? Но не могу заставить его работать с решениями, связанными выше.

3 ответа

Решение

Как вы упомянули, lit-element по умолчанию использует shadow dom, поскольку имеет много преимуществ при создании повторно используемых компонентов.

Тем не менее, вы можете отказаться от него и использовать "легкий" dom, который будет отображать содержимое компонента в главном dom, что, в свою очередь, сделает этот контент доступным с помощью таких вещей, как document.getElementById() или же document.querySelector()

Вот минимальный пример того, как использовать light dom в компоненте на основе освещенных элементов (и вот глюк, где вы можете увидеть его в действии)

class MyElement extends LitElement {  
  render() {
    return html`
      <section>
        ... My content ...
      </section>
      <div id="myElementContainer">
        This is a container inside my element
      </div>
    `;
  }

  createRenderRoot() {
    // this is what overrides lit-element's behavior so that the contents don't render in shadow dom
    return this;
  }

}

Просто имейте в виду, что в этом случае вы должны использовать этот компонент только один раз в вашем приложении из-за того, как getElementById() работает и что вы не сможете использовать <slot> в вашем компоненте, так как эта функция доступна только для теневого домена

Итак, ищите возможность, используя, может быть, слоты, чтобы выставить элемент теневого дома на светлый дом? Но не могу заставить его работать с решениями, связанными выше.

На самом деле то, что вы должны сделать, это наоборот: разоблачить <div> быть выбранным в легком DOM и интегрировать его в Shadow DOM через <slot> пометьте, если вам нужно.

this.innerHTML = '<div id="CONTAINER NAME"></div>'
return html`
      ${SharedStyles}    
      <section>
        ...my content...

      </section>
      <slot></slot>
    `

Вы также можете сделать это программно через слотирование

  1. Добавлять.setAttribute('slot','slot-inside-your-shadow-dom')к вашему элементу, который необходимо запросить через.getElementById()
  2. Добавьте свой элемент где-нибудь внутриdocument(т.е.document.appendChild(element))

Теперь ваш элемент должен появиться внутри слота shadowDom, но его также можно запросить черезdocument.querySelector(и т. д.)

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