HTML web bileşeni gölge DOM stilini kullanmaz

Aug 15 2020

Vanilya web bileşeni veya HTML öğesi oluşturdum. Yalnızca iki bağlantı görüntüler.

Bir şeyi kapsüllemek için gölge DOM kullanıyorum. Ancak, kapsüllenmiş görünmüyor. DOM ağacında, iyi olan # shadow-root içindedir.

Web bileşeni neden web bileşenim için şablonda sağladığım stil yerine genel stili kullanıyor?

Metin kırmızı ve yeşil olmasını bekliyordum.

class MyEl extends HTMLElement {
  constructor() {
    super();
    this.shadow = this.attachShadow({ mode: "open" });
  }

  connectedCallback() {
    const template = `
      <style>
        a {
          color: green;
        }
      </style>
      <slot></slot>`;
    this.shadow.innerHTML = template;
  }
}

window.customElements.define("my-el", MyEl);
a {
  color: red
}
  <my-el>
    <a href="example.com">Item1</a>
    <a href="example.com">Item2</a>
  </my-el>

Yanıtlar

1 AlanDávalos Aug 17 2020 at 15:12

Bu sorunun zaten kabul edilmiş bir cevabı olsa da, bir yuvanın çocuklarını shadowRoot'a taşımak çoğu kullanım durumu için arzu edilmez.

Muhtemelen yapmak istediğiniz şey ::slotted()seçiciyi kullanmaktır .

::slotted()Seçici aracılığıyla bir yuvanın alt öğelerine uygulanan stillerin yalnızca "varsayılan" stiller olarak davrandığını ve hafif DOM'da stiller kullanılarak yine de geçersiz kılınabileceğini unutmayın.

Örneğin, snippet'inizin bu düzenlenmiş sürümünü kontrol edin:

Gördüğünüz gibi, bu sefer çocukları herhangi bir yuvasına my-elsabitlemek ( <a>) için hem bir renk hem de bir metin süsleme stili uygulamaya çalışıyor .

Bununla birlikte, hafif dom, a.specialrengi geçersiz kılan bir seçicimiz var, bu nedenle <a class="special">yeşil değil kırmızı olacak

class MyEl extends HTMLElement {
  constructor() {
    super();
    this.shadow = this.attachShadow({ mode: "open" });
  }

  connectedCallback() {
    const template = `
      <style>
        ::slotted(a) {
          color: green;
          text-decoration: none;
        }
      </style>
      <slot></slot>`;
    this.shadow.innerHTML = template;
  }
}

window.customElements.define("my-el", MyEl);
a.special {
  color: red
}
  <my-el>
    <a href="example.com">Item1</a>
    <a class="special" href="example.com">Item2</a>
  </my-el>

1 Danny'365CSI'Engelman Aug 15 2020 at 23:44

Tam, ayrıntılı açıklama şu şekildedir : :: shadowDOM yuvasındaki yuvalanmış çocuklar için yuvalı CSS seçici

TL; DR

Bağlantılarınız lightDOM içindedir ve bu nedenle DOM'a göre biçimlendirilmiştir (kodunuzda DOM belgenizde)
Düğümleri lightDOM'dan shadowDOM'a taşımak bir "çözümdür"; ama o zaman slot kullanmıyorsun.

Bilginize, kodunuz şu şekilde sıkıştırılabilir:

class MyEl extends HTMLElement {
  constructor() {
    super().attachShadow({ mode: "open" })
           .innerHTML = `<style>a{color:green}</style><slot></slot>`;

  }
}

window.customElements.define("my-el", MyEl);

StackOverflow Araması ile SLOT ile ilgili daha fazla yanıt bulunabilir: Özel Öğeler SLOT'ları

KresimirPendic Aug 15 2020 at 19:57

bu çizgiye dikkat edin, öğeleri gölgeye taşımanız / kopyalamanız gerekir, örneğin:

this.shadow.innerHTML = this.innerHTML + template;

Bunu, gölge dom öğelerine yalnızca satır içi stilin uygulanacağını göstermek için ekledim .. yani SD'de kopyalanan bağlantılar sizin stilinizi kullanıyor :)

Öyleyse kırmızı olacak GLOBAL, yeşilSHADOW unsur olacak

class MyEl extends HTMLElement {
  constructor() {
    super();
  }

  connectedCallback() {
    this.shadow = this.attachShadow({ mode: "open" });
    const template = `
      <style>
        a {
          color: green;
        }
      </style>
      <slot></slot>`;
    this.shadow.innerHTML = this.innerHTML + template;
  }
}

window.customElements.define("my-el", MyEl);
a {
  color: red
}
<my-el>
    <a href="example.com">Item1</a>
    <a href="example.com">Item2</a>
  </my-el>