Пользовательский элемент html, содержимое слота добавляется после # shadow-root

Я пытаюсь создать собственный элемент с помощью js. это мой пользовательский элемент

class ImageBackground extends HTMLElement {
  createdCallback() {
    let src = this.hasAttribute('src') ? this.getAttribute('src') : '/static/images/user.png'
    let className = `img-bg ${this.hasAttribute('className') ? this.getAttribute('className') : ''}`
    let isLazy = this.getAttribute('lazy') !== false

    const slotContent = document.createElement('slot')
    slotContent.setAttribute('name', 'slot-content')

    const wrapper = document.createElement('div')
    wrapper.appendChild(slotContent)
    wrapper.style.backgroundImage = `url("${src}")`
    wrapper.style.backgroundSize = 'cover'
    wrapper.style.backgroundPosition = 'center'
    wrapper.style.height = '300px'
    wrapper.setAttribute('class', className)

    this.createShadowRoot().appendChild(wrapper)
  }
}

document.registerElement('img-bg', ImageBackground)

а это мой шаблон мопса

img-bg(src="/static/images/email.svg")
      p(slot="slot-content") cek

Я хочу добавить элемент p внутри слота. но элемент p добавлен после # shadow-root.

введите описание изображения здесь

кто-нибудь может это решить ... :( извините за плохой английский


person cahyowhy    schedule 17.05.2018    source источник
comment
примечание: вы смешиваете синтаксис Shadow DOM v0 (createShadowRoot) и Shadow DOM v1 (‹slot›). Я не уверен, что это сработает. Вы бы предпочли использовать метод attachShadow (Shadow DOM v1) для создания Shadow DOM. Также используйте синтаксис Custum Element v1, не читая v0.   -  person Supersharp    schedule 17.05.2018


Ответы (2)


Тег <slot> используется для импорта дочерних элементов элемента в <slot>, а не для размещения ваших собственных дочерних элементов.

Лучшее, что вы могли сделать, - это обернуть ваш <slot> чем-то другим, а затем поместить тег <p> компонента сразу после <slot>.

В качестве альтернативы и не рекомендуется:

Если вы хотите добавить какой-либо тег, сгенерированный компонентом, в слот, вам нужно поместить тег как дочерний элемент вашего элемента, а не в shadowDOM. Пока он размещается как правильный дочерний элемент, соответствующий требованиям <slot>, чем он должен отображаться в <slot>.

class MyEl extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({mode:'open'}).innerHTML = `
    <style>
      .wrapper {
        border: 1px solid black;
        padding: 5px;
      }
      ::slotted(*) {
        background-color: #8F8; 
        margin: 1px;
        padding: 5px;
      }
    </style>
    <p>Before Slot</p>
    <div class="wrapper"><slot>Hi There</slot></div>
    <p>After Slot</p>
    `;
  }

  connectedCallback() {
  }
}

customElements.define('my-el', MyEl);

function addChild() {
  var el = document.querySelector('my-el');
  var p = document.createElement('p');
  p.textContent = "New stuff as a child.";
  el.appendChild(p);
}

var button = document.querySelector('#one');
button.addEventListener('click', addChild);
p {
  font-family: tahoma;
}

my-el p {
  font-weight: bold;
}
<p>Before Element</p>
<my-el>
  <p>Stuff in the slot</p>
</my-el>
<p>After Element</p>
<hr/>
<button id="one">Add Child</button>

Таким образом, единственный способ добавить в слот - это добавить к элементу дочерние элементы.

Вероятно, это не лучший вариант, поскольку вы изменяете контент, созданный пользователем вашего компонента. И это могло испортить их код, CSS или и то, и другое.

person Intervalia    schedule 21.05.2018

<slot> определен в Shadow DOM v1. Поэтому вы должны использовать attachShadow() вместо createShadowRoot():

this.attachShadow({ mode:'open'}).appendChild(wrapper)
person Supersharp    schedule 19.05.2018