我有一个不使用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。但是,一旦外部元素将我包含在他们的影子DOM中,那么事情就会崩溃。
答案 0 :(得分:0)
如果您要创建一个不使用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中。