未捕获的DOMException:无法在'ShadowRoot'上设置'adoptedStyleSheets'属性:无法采用非构造样式表 没有可构造的样式表

问题描述

是否可以在shadowRoot.adoptedStyleSheets中使用样式元素?

<style id=style>
  h1 { color: red }
</style>
<script>
  customElements.define('test-elem',class extends HTMLElement {
    constructor () {
      super()
      const shadow = this.attachShadow({ mode: 'closed' })
      shadow.adoptedStyleSheets = [style.sheet]
      shadow.append(template.content.cloneNode(true))
    }
  })
</script>

解决方法

<style id="sourcestyle">
  h1 {
    color: green
  }
</style>

<my-element></my-element>

<script>
  customElements.define('my-element',class extends HTMLElement {
    constructor() {
      const sheet = new CSSStyleSheet();
      sheet.replace(document.getElementById("sourcestyle").innerHTML);

      super() // returns this/element scope
        .attachShadow({ mode: 'open' }) // both sets and returns this.shadowRoot
        .innerHTML = `<h1>Hello World!</h1>`;

      this.shadowRoot.adoptedStyleSheets = [sheet];
    }
  })
</script>

最好在组件外部构造 可重用 样式表,
而不创建全局<style>

  const sheet = new CSSStyleSheet();
  sheet.replace(`h1{color:green}`);

没有可构造的样式表

(可构造CSS并非在所有浏览器中都适用)

否则,您也可以使用以下方法移动 <style>
(或在要重用时使用cloneNode)

  this.shadowRoot.append(document.getElementById("sourcestyle"));

由于它是一个全局工作表,因此您可能要针对主DOM禁用它

  <style id="sourcestyle" onload="this.disabled=true">
    h1 {
      color: green
    }
  </style>

,然后一旦它处于shadowDOM中,就撤消已禁用的对象:

  this.shadowRoot.getElementById("sourcestyle").disabled=false;