是否可以保留自定义元素的内部 html?

Jam*_*s M 4 html javascript web-component native-web-component

使用自定义元素,我想对自定义元素内的元素进行样式设置,但是当我定义该元素时,除了影子 dom 之外的所有内容都会消失。

如何将内容从元素移动到 Shadow dom?我已经<div class="wrapper">在阴影内有一个包装元素 ( ),但尝试使用

wrapper.innerHTML = this.innerHTML;
Run Code Online (Sandbox Code Playgroud)

不起作用。

超文本标记语言

<site-card>
  <section title>
    ...
  </section>
  <section body>
    ...
  </section>
  <section actions>
    <button class="modern small">Action</button>
    <button class="modern small">Action 2</button>
  </section>
</site-card>
Run Code Online (Sandbox Code Playgroud)

JS

"use strict";
class cardElement extends HTMLElement {
    constructor() {
        super();
        var shadow = this.attachShadow({mode: 'open'});
        var wrapper = document.createElement('div');
        wrapper.setAttribute('class','wrapper');
        wrapper.innerHTML = this.innerHTML;
        var style = document.createElement('style');
        style.textContent = ... /* CSS removed to shorten. */
        shadow.appendChild(style);
        shadow.appendChild(wrapper);
    };
};
customElements.define('site-card', cardElement);
Run Code Online (Sandbox Code Playgroud)

Int*_*lia 5

如果您想从自定义元素外部控制 CSS,那么只需使用<slot>. <slot>将子元素嵌入到槽中,但将 CSS 控制留给元素外部。

class cardElement extends HTMLElement {
  constructor() {
    super();
    var shadow = this.attachShadow({mode: 'open'});
    var wrapper = document.createElement('slot');
    var style = document.createElement('style');
    style.textContent = `
    [title] {
      background-color: #060;
      color: #FFF;
    }
    [body] {
      background-color: #600;
      color: #FFF;
    }
    [actions] {
      background-color: #006;
      color: #FFF;
    }
    `;
    shadow.appendChild(style);
    shadow.appendChild(wrapper);
  };
};
customElements.define('site-card', cardElement);
Run Code Online (Sandbox Code Playgroud)
[title] {
  background-color: #0F0;
  color: #000;
}
[body] {
  background-color: #F00;
  color: #000;
}
[actions] {
  background-color: #00F;
  color: #000;
}
Run Code Online (Sandbox Code Playgroud)
<site-card>
  <section title>
    This is the title
  </section>
  <section body>
    This is the body
  </section>
  <section actions>
    <button class="modern small">Action</button>
    <button class="modern small">Action 2</button>
  </section>
</site-card>
Run Code Online (Sandbox Code Playgroud)

如果你想从元素内部控制 CSS,那么你需要迁移子元素。但这不能构造函数中完成。规范的这一部分解释了构造函数的限制。

你需要把孩子搬到connectedCallback

class cardElement extends HTMLElement {
  constructor() {
    super();
    var shadow = this.attachShadow({mode: 'open'});
    this._wrapper = document.createElement('div');
    var style = document.createElement('style');
    style.textContent = `
    [title] {
      background-color: #060;
      color: #FFF;
    }
    [body] {
      background-color: #600;
      color: #FFF;
    }
    [actions] {
      background-color: #006;
      color: #FFF;
    }
    `;
    shadow.appendChild(style);
    shadow.appendChild(this._wrapper);
  };
  
  connectedCallback() {
    while(this.firstElementChild) {
      this._wrapper.appendChild(this.firstElementChild);
    }
  }
};
customElements.define('site-card', cardElement);
Run Code Online (Sandbox Code Playgroud)
[title] {
  background-color: #0F0;
  color: #000;
}
[body] {
  background-color: #F00;
  color: #000;
}
[actions] {
  background-color: #00F;
  color: #000;
}
Run Code Online (Sandbox Code Playgroud)
<site-card>
  <section title>
    This is the title
  </section>
  <section body>
    This is the body
  </section>
  <section actions>
    <button class="modern small">Action</button>
    <button class="modern small">Action 2</button>
  </section>
</site-card>
Run Code Online (Sandbox Code Playgroud)

我建议避免使用,innerHTML因为这会清除可能已经存在的任何事件处理程序等。实际上可能会更慢,具体取决于直系子代的数量。它还可能会弄乱任何可能是自定义元素的子元素。