Как обернуть отдельные элементы - PullRequest
0 голосов
/ 25 февраля 2020

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

Предположим, что разметка выглядит примерно так:

<custom-element>
  <div name="item">item 1</div>
  <div name="item">item 2</div>
</custom-element>

В настоящее время рендеринг похож на:

<custom-element>
  <div class="wrap">
    <div name="item">item 1</div>
    <div name="item">item 2</div>
  </div>
</custom-element>

Как бы я go обернул элементы со слотами для вывода аналогично:

<custom-element>
  <div class="wrap">
    <div name="item">item 1</div>
  </div>
  <div class="wrap">
    <div name="item">item 2</div>
  </div>
</custom-element>

Мой текущий (некорректный) подход:

customElements.define('custom-element', class MyCustomElement extends HTMLElement {

  constructor(...args) {
    super(...args);

    let shadow = this.attachShadow({mode: open});
    shadow.innerHTML = `
      <div class="wrap">
        <slot name="item"></slot>
      </div>
    `;
  }
});

1 Ответ

1 голос
/ 26 февраля 2020

Я бы порекомендовал вам изменить свой подход к упаковке детей. Простейшим способом было бы просто добавить отсутствующий 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>
...