Я бы порекомендовал вам изменить свой подход к упаковке детей. Простейшим способом было бы просто добавить отсутствующий HTML как дочерний элемент для слота div, как показано ниже. Вы по-прежнему сможете стилизовать слот-элемент с помощью псевдоселектора ::slotted
.
customElements.define('custom-element', class MyCustomElement extends HTMLElement {
constructor(...args) {
super(...args);
let shadow = this.attachShadow({ mode: 'open' });
shadow.innerHTML = `
<style>
::slotted([slot="item"]) {
border: 1px solid black;
padding: 15px;
}
</style>
<slot name="item"></slot>
`;
}
});
<custom-element>
<div slot="item">
<div class="wrap">item 1</div>
</div>
<div slot="item">
<div class="wrap">item 2</div>
</div>
</custom-element>
Причина такого подхода заключается в том, что обертка в конечном итоге принадлежит элементу child и должна поставляться с каждым дочерним элементом. Результат будет аналогичен тому, что вы запрашиваете.
Хотя, если вы хотите динамически добавить обертку к элементу, вы можете сделать это с событием slotchange
. Событие вызывается всякий раз, когда слот заполнен, и его можно прослушивать из элемента ShadowRoot
. В обратном вызове события l oop над assignedElements
(которые являются элементами в слоте) и измените их значение innerHTML
.
customElements.define('custom-element', class MyCustomElement extends HTMLElement {
constructor(...args) {
super(...args);
let shadow = this.attachShadow({mode: 'open'});
shadow.innerHTML = `
<slot name="item"></slot>
`;
shadow.addEventListener('slotchange', event => {
const { target } = event;
const assignedElements = target.assignedElements();
for (const element of assignedElements) {
element.innerHTML = `
<div class="wrap">
${element.textContent}
</div>
`;
}
});
}
});
.wrap {
border: 1px solid black;
padding: 15px;
}
<custom-element>
<div slot="item">item 1</div>
<div slot="item">item 2</div>
</custom-element>