0

我有一个未使用 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。但是一旦外部元素将我包含在他们的 shadowDOM 中,那么事情就会分崩离析。

4

1 回答 1

1

如果您正在创建一个不使用 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 中,或者document.head如果没有 shadowRoot 则放入。

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

在我的中,您会看到该<style>标签添加了一个属性,该属性component使用组件名称的值调用。就我而言component="my-el"

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

你不能仅仅因为你没有使用它就假设你的组件不会在 shadow DOM 中。使用上面的示例来保护自己。

边注

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

于 2018-02-22T21:46:01.087 回答