Вставить содержимое из <template> в <slot>

Я хочу получить содержимое шаблона, внедрить его в пользовательский элемент с теневым DOM и применить стили к span внутри template с помощью ::slotted селектор, но это не похоже на работу, как ожидалось.

<!doctype html>
<html lang="en">
    <head>
        <template id="template">
            <span>element from template</span>
        </template>
    </head>
    <body>
        <script type="text/javascript">
            class WithShadowDom extends HTMLElement {
                constructor() {
                    super();
                    const shadowRoot = this.attachShadow({mode: 'open'});
                    shadowRoot.innerHTML = `
                        <style>
                            ::slotted(span) {
                                font-size: 25px;
                            }
                        </style>
                    `;
                    shadowRoot
                        .appendChild(document.createElement('slot'))
                        .appendChild(
                            document.getElementById('template').content.cloneNode(true)
                        );
                }
            }
            window.customElements.define('with-shadow-dom', WithShadowDom);
            const myCustomElement = document.createElement('with-shadow-dom');
            document.body.appendChild(myCustomElement);
        </script>
    </body>
</html>

Следующая часть не работает, как ожидалось. font-size CSS не применяется.

shadowRoot
    .appendChild(document.createElement('slot'))
    .appendChild(document.getElementById('template').content.cloneNode(true));

Хотя при прямом добавлении ребенка span внутри пользовательского элемента font-size применяется

const span = document.createElement('span');
span.innerHTML = 'asdffad';
shadowRoot
    .appendChild(document.createElement('slot'))
    .appendChild(span);

1 ответ

Решение

Вы добавили промежуток к теневому дому. Вы должны добавить его в Light DOM вместо этого, если вы хотите, чтобы он был вставлен в <slot> место.

connectedCallback() {
    //template content
    this.appendChild(document.getElementById('template').content.cloneNode(true));
    //span element
    const span = document.createElement('span');
    span.innerHTML = 'asdffad';
    this.appendChild(span);
}

NB. Вы не должны добавлять контент в DOM light в constructor(), Вместо этого сделайте это в connectedCallback() метод.

Если вы посмотрите на панель " Элементы" в консоли разработчика, вы увидите, что при добавлении фрагмента или элемента HTML в результат получается другой результат. <slot> и на свет DOM.

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