【问题标题】:Why does my Web Component CSS not show? I am not using shadowDOM为什么我的 Web 组件 CSS 不显示?我没有使用 shadowDOM
【发布时间】:2018-08-02 21:56:24
【问题描述】:
我有一个未使用 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 中,事情就会崩溃。
【问题讨论】:
标签:
css
web-component
shadow-dom
native-web-component
【解决方案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 中,如果没有 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 中。