HTML web component 没有使用 shadow DOM 样式
HTML web component does not use shadow DOM style
我创建了一个 vanilla web 组件或 HTML 元素。它只显示两个链接。
为了封装这个东西,我使用了 shadow DOM。但是它似乎没有被封装。在 DOM 树中,它位于 #shadow-root 中,这很好。
为什么 Web 组件使用全局样式而不是我在模板中为我的 Web 组件提供的样式?
文本是红色的,我希望它是绿色的。
class MyEl extends HTMLElement {
constructor() {
super();
this.shadow = this.attachShadow({ mode: "open" });
}
connectedCallback() {
const template = `
<style>
a {
color: green;
}
</style>
<slot></slot>`;
this.shadow.innerHTML = template;
}
}
window.customElements.define("my-el", MyEl);
a {
color: red
}
<my-el>
<a href="example.com">Item1</a>
<a href="example.com">Item2</a>
</my-el>
观察这一行,你必须 move/copy 个元素来遮蔽例如:
this.shadow.innerHTML = this.innerHTML + template;
我添加这个是为了证明只有内联样式会应用于阴影 dom 元素..所以在 SD 中复制的链接正在使用您的样式:)
所以红色将是GLOBAL
,绿色将是SHADOW
个元素
class MyEl extends HTMLElement {
constructor() {
super();
}
connectedCallback() {
this.shadow = this.attachShadow({ mode: "open" });
const template = `
<style>
a {
color: green;
}
</style>
<slot></slot>`;
this.shadow.innerHTML = this.innerHTML + template;
}
}
window.customElements.define("my-el", MyEl);
a {
color: red
}
<my-el>
<a href="example.com">Item1</a>
<a href="example.com">Item2</a>
</my-el>
完整、详细的解释在:
TL;DR
您的链接很清晰DOM,因此其样式由其 DOM(在您的代码中,文档 DOM)
将节点从 lightDOM 移动到 shadowDOM 是一个“解决方案”;但是你当时没有使用插槽。
仅供参考,您的代码可以压缩为:
class MyEl extends HTMLElement {
constructor() {
super().attachShadow({ mode: "open" })
.innerHTML = `<style>a{color:green}</style><slot></slot>`;
}
}
window.customElements.define("my-el", MyEl);
更多与 SLOT 相关的答案可以通过 Whosebug 搜索找到:Custom Elements SLOTs
虽然这个问题已经有了公认的答案,但对于大多数用例来说,将插槽的子级移动到 shadowRoot 是不可取的。
您可能想要做的是使用 ::slotted()
选择器。
请记住,通过 ::slotted()
选择器应用于插槽子项的样式仅作为“默认”样式,仍然可以使用 light DOM.[=19 中的样式覆盖=]
例如,检查您的代码段的这个编辑版本:
如您所见,这次 my-el
尝试同时应用颜色和 text-decoration 样式来将 (<a>
) 子级锚定在它的任何插槽中。
但是,在灯光 dom 中,我们有一个覆盖颜色的 a.special
选择器,因此 <a class="special">
将是红色,而不是绿色
class MyEl extends HTMLElement {
constructor() {
super();
this.shadow = this.attachShadow({ mode: "open" });
}
connectedCallback() {
const template = `
<style>
::slotted(a) {
color: green;
text-decoration: none;
}
</style>
<slot></slot>`;
this.shadow.innerHTML = template;
}
}
window.customElements.define("my-el", MyEl);
a.special {
color: red
}
<my-el>
<a href="example.com">Item1</a>
<a class="special" href="example.com">Item2</a>
</my-el>
我创建了一个 vanilla web 组件或 HTML 元素。它只显示两个链接。
为了封装这个东西,我使用了 shadow DOM。但是它似乎没有被封装。在 DOM 树中,它位于 #shadow-root 中,这很好。
为什么 Web 组件使用全局样式而不是我在模板中为我的 Web 组件提供的样式?
文本是红色的,我希望它是绿色的。
class MyEl extends HTMLElement {
constructor() {
super();
this.shadow = this.attachShadow({ mode: "open" });
}
connectedCallback() {
const template = `
<style>
a {
color: green;
}
</style>
<slot></slot>`;
this.shadow.innerHTML = template;
}
}
window.customElements.define("my-el", MyEl);
a {
color: red
}
<my-el>
<a href="example.com">Item1</a>
<a href="example.com">Item2</a>
</my-el>
观察这一行,你必须 move/copy 个元素来遮蔽例如:
this.shadow.innerHTML = this.innerHTML + template;
我添加这个是为了证明只有内联样式会应用于阴影 dom 元素..所以在 SD 中复制的链接正在使用您的样式:)
所以红色将是GLOBAL
,绿色将是SHADOW
个元素
class MyEl extends HTMLElement {
constructor() {
super();
}
connectedCallback() {
this.shadow = this.attachShadow({ mode: "open" });
const template = `
<style>
a {
color: green;
}
</style>
<slot></slot>`;
this.shadow.innerHTML = this.innerHTML + template;
}
}
window.customElements.define("my-el", MyEl);
a {
color: red
}
<my-el>
<a href="example.com">Item1</a>
<a href="example.com">Item2</a>
</my-el>
完整、详细的解释在:
TL;DR
您的链接很清晰DOM,因此其样式由其 DOM(在您的代码中,文档 DOM)
将节点从 lightDOM 移动到 shadowDOM 是一个“解决方案”;但是你当时没有使用插槽。
仅供参考,您的代码可以压缩为:
class MyEl extends HTMLElement {
constructor() {
super().attachShadow({ mode: "open" })
.innerHTML = `<style>a{color:green}</style><slot></slot>`;
}
}
window.customElements.define("my-el", MyEl);
更多与 SLOT 相关的答案可以通过 Whosebug 搜索找到:Custom Elements SLOTs
虽然这个问题已经有了公认的答案,但对于大多数用例来说,将插槽的子级移动到 shadowRoot 是不可取的。
您可能想要做的是使用 ::slotted()
选择器。
请记住,通过 ::slotted()
选择器应用于插槽子项的样式仅作为“默认”样式,仍然可以使用 light DOM.[=19 中的样式覆盖=]
例如,检查您的代码段的这个编辑版本:
如您所见,这次 my-el
尝试同时应用颜色和 text-decoration 样式来将 (<a>
) 子级锚定在它的任何插槽中。
但是,在灯光 dom 中,我们有一个覆盖颜色的 a.special
选择器,因此 <a class="special">
将是红色,而不是绿色
class MyEl extends HTMLElement {
constructor() {
super();
this.shadow = this.attachShadow({ mode: "open" });
}
connectedCallback() {
const template = `
<style>
::slotted(a) {
color: green;
text-decoration: none;
}
</style>
<slot></slot>`;
this.shadow.innerHTML = template;
}
}
window.customElements.define("my-el", MyEl);
a.special {
color: red
}
<my-el>
<a href="example.com">Item1</a>
<a class="special" href="example.com">Item2</a>
</my-el>