为什么我的 Web 组件 CSS 不显示?我没有使用 shadowDOM
Why does my Web Component CSS not show? I am not using shadowDOM
我有一个未使用 shadowDOM 的原生 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 中,事情就会分崩离析。
如果您正在创建一个不使用 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
,如果不存在则只添加样式。
您不能仅仅因为您没有使用它就假设您的组件不会在影子中 DOM。使用上面的示例来保护自己。
旁注
If you are using shadow DOM then this problem goes away since your have to place your CSS into your own shadowRoot.
我有一个未使用 shadowDOM 的原生 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 中,事情就会分崩离析。
如果您正在创建一个不使用 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
,如果不存在则只添加样式。
您不能仅仅因为您没有使用它就假设您的组件不会在影子中 DOM。使用上面的示例来保护自己。
旁注
If you are using shadow DOM then this problem goes away since your have to place your CSS into your own shadowRoot.