Слот LitElement с appendChild не работает

Когда я попытался добавить дочерний слот к моему компоненту на LitElement, он не работал и не принял его создание.

render() {
    return html `<div class="wizard-container ${this.className}"></div>`;
  }

  firstUpdated() {
    let wizardContainer = this.shadowRoot.querySelector('.wizard-container');
    for (let i = 0; i < this.steps; i++) {
      let slot = document.createElement('SLOT');
      slot.setAttribute('name', 'step_' + (i + 1))
      wizardContainer.appendChild(slot);
    };
  }

person Ahmed A. Mahmoud    schedule 30.09.2019    source источник


Ответы (2)


Элемент - часть технологического пакета веб-компонентов - представляет собой заполнитель внутри веб-компонента, который можно заполнить собственной разметкой, что позволяет создавать отдельные деревья DOM и представлять их вместе.

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

<element-details>
  <span slot="element-name">slot</span>
  <span slot="description">A placeholder inside a web
    component that users can fill with their own markup,
    with the effect of composing different DOM trees
    together.</span>
  <dl slot="attributes">
    <dt>name</dt>
    <dd>The name of the slot.</dd>
  </dl>
</element-details>
person Elbaz    schedule 30.09.2019

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

Например, вы можете создать массив из своей переменной steps и перебрать его с помощью функции map для создания таких слотов:

render() {
  return html`<div class="wizard-container ${this.className}">
    ${Array.from({ length: this.steps }, (v, k) => k).map(
      item =>
        html`<slot name="step_${item}"><div>Default content ${item}</div></slot>`
    )}
  </div>`;
}

А затем используйте свой компонент следующим образом:

<my-element steps="3">
  <div slot="step_1">Custom content</div>
</my-element>

В результате получится что-то вроде:

Содержимое по умолчанию 0 Пользовательское содержимое Содержимое по умолчанию 2

Вот живая демонстрация

Что касается причины, по которой ваш предыдущий код работал не так, как вы ожидали, LitElement по большей части ожидает, что вы сохраните код, связанный с шаблонами в функции рендеринга, поскольку все, что вы добавляете с помощью appendChild или аналогичных функций DOM, будет "удалено" в следующий раз, когда компонент обновится, поэтому вам придется добавлять его после каждого обновления самостоятельно

Добавляя слоты непосредственно в метод рендеринга, вы гарантируете, что они не будут удалены неожиданным образом.

person Alan Dávalos    schedule 30.09.2019
comment
Спасибо за вашу поддержку, ваш ответ тоже правильный, но другой более практичный и отвечает моим потребностям. - person Ahmed A. Mahmoud; 30.09.2019