为什么我的Web组件CSS没有显示?我没有使用shadowDOM

时间:2018-02-22 21:46:01

标签: css web-component shadow-dom native-web-component

我有一个不使用shadowDOM的Native V1组件,因此我将CSS放在<head>中。但是,当其他人使用我的组件时,我的CSS不再有效。

仅当他们的组件使用shadowDOM时才会发生这种情况。

我的组件的示例代码:

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

  connectedCallback() {
    this.innerHTML = `<div class="spaced"><button class="happy-btn">I'm Happy</button></div>
    <div class="spaced"><button class="sad-btn">I'm Sad</button></div>`;
  }
}

// Define our web component
customElements.define('my-el', MyEl);
button {
  padding: 8px 20px;
}

.happy-btn {
  background-color: pink;
}

.sad-btn {
  background-color: #007;
  color: white;
}
<my-el></my-el>

我的CSS已加载到<head>标记中,因为我没有使用shadowDOM。但是,一旦外部元素将我包含在他们的影子DOM中,那么事情就会崩溃。

1 个答案:

答案 0 :(得分:0)

如果您要创建一个不使用ShadowDOM的组件,您可能仍需要将CSS添加到shadowRoot中。如果其他人将您的组件放入shadowDOM,那么您必须将CSS添加到他们的shadowRoot中。您可以使用以下代码执行此操作:

const myStyle = document.createElement('style');
myStyle.setAttribute('component', 'my-el');
myStyle.textContent = `    button {
  padding: 8px 20px;
}
.happy-btn {
  background-color: pink;
}

.sad-btn {
  background-color: #007;
  color: white;
}`;

function addCss(el, selector, styleEl) {
  // Check to see if we have been placed into a shadow root.
  // If we have then add our CSS into that shadow root.
  let doc;
  try {
    doc = el.getRootNode();
    if (doc === document) {
      doc = document.head;
    }
  }
  catch(_ex) { doc = document.head; } // Shadow DOM isn't supported.

  if (!doc.querySelector(selector)) {
    doc.appendChild(styleEl.cloneNode(true));
  }
}

class MyEl extends HTMLElement {
  constructor() {
    super();
    addCss(this, 'style[component="my-el"]', myStyle);
  }
  connectedCallback() {
    this.innerHTML = `<div class="spaced"><button class="happy-btn">I'm Happy</button></div>
    <div class="spaced"><button class="sad-btn">I'm Sad</button></div>`;
  }
}
customElements.define('my-el', MyEl);

class TheirEl extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({mode:'open'});
    this.shadowRoot.innerHTML = `<hr/><my-el></my-el><hr/><my-el></my-el><hr/>`;
  }
}
customElements.define('their-el', TheirEl);
<their-el></their-el>

函数addCss会将CSS放入正确的shadowRoot,如果没有shadowRoot,则放入document.head

您必须在构造函数中调用addCss以将CSS放在正确的位置。只要您有唯一的选择器来识别<style>标记,此例程还会确保您不会添加两次。

在我的文章中,您会看到<style>标记添加了一个名为component的属性,其中包含组件名称的值。就我而言component="my-el"

然后我使用选择器'style [component =“my-el”]'来查看该标签是否已经在shadowRoot中,如果没有shadowRoot则使用document.head,并且仅添加样式尚不存在。

您不能仅因为未使用它而假设您的组件不在shadow DOM中。使用上面的例子来保护自己。

旁注

  

如果您使用的是shadow DOM,那么这个问题就会消失,因为您必须将CSS放入自己的shadowRoot中。