在CSS中将:host
和:defined
组合在一起,同时将:host()
伪类作品组合在一起时,是不可能的吗?
如下面的示例所示,
:host:defined { display: block; }
无效,而
:host(:defined) { display: block; }
有效。
class CustomElement extends HTMLElement {
constructor() {
super();
this.shadow = this.attachShadow({ mode: 'closed' });
const css = `
:host { display: none; }
:host:defined { display: block; }
`;
this.styles = document.createElement('style');
this.styles.innerHTML = css;
}
connectedCallback() {
const div = document.createElement('div');
div.innerHTML = `<code><${this.tagName.toLowerCase()}></code> connected!`;
this.shadow.appendChild(this.styles);
this.shadow.appendChild(div);
}
}
class OtherCustomElement extends HTMLElement {
constructor() {
super();
this.shadow = this.attachShadow({ mode: 'closed' });
const css = `
:host { display: none; }
:host(:defined) { display: block; }
`;
this.styles = document.createElement('style');
this.styles.innerHTML = css;
}
connectedCallback() {
const div = document.createElement('div');
div.innerHTML = `<code><${this.tagName.toLowerCase()}></code> connected!`;
this.shadow.appendChild(this.styles);
this.shadow.appendChild(div);
}
}
customElements.define('custom-element', CustomElement);
customElements.define('other-custom-element', OtherCustomElement);
<custom-element></custom-element>
<other-custom-element></other-custom-element>
上述关于代码笔的代码示例:https://codepen.io/connexo/pen/GRKEGax
答案 0 :(得分:2)
在the specification中,我们可以看到:
:host
伪类在影子树的上下文中进行评估时,与影子树的影子宿主匹配。在任何其他情况下,它都不匹配函数
:host()
的伪类具有以下语法::host( <compound-selector-list> )
在阴影树的上下文中进行评估时,如果阴影宿主在其正常上下文中匹配选择器参数,则它与阴影树的阴影宿主匹配。在任何其他情况下,它都不匹配。
基本上,:host
将与影子主机匹配,仅此而已。您无法将其与任何其他选择器组合使用。第二种语法允许您在()
内添加选择器。
如果您参考规范中显示的示例:
假设您有一个带有影子树的组件,如下所示:
<x-foo class="foo">
<"shadow tree">
<div class="foo">...</div>
</>
</x-foo>
对于阴影树中的样式表:
:host
与<x-foo>
元素匹配。
x-foo
不匹配任何内容。
.foo
仅匹配元素。
.foo:host
不匹配
:host(.foo)
匹配元素。
注意(2)和(4)。 (2)什么也没选择,因为没有公共选择器可以在阴影树之外选择。只有:host
和:host()
可以这样做。 (4)没有选择任何内容,因为:host
被设计为单独用于选择 shadow主机,但是如果要添加其他选择器,则必须使用:host()
(5)。
这里是一个基本的例子来说明:
class CustomElement extends HTMLElement {
constructor() {
super();
this.shadow = this.attachShadow({ mode: 'closed' });
const css = `
:host.box { color:red; }
`;
this.styles = document.createElement('style');
this.styles.innerHTML = css;
}
connectedCallback() {
const div = document.createElement('div');
div.innerHTML = `<code><${this.tagName.toLowerCase()}></code> connected!`;
this.shadow.appendChild(this.styles);
this.shadow.appendChild(div);
}
}
class OtherCustomElement extends HTMLElement {
constructor() {
super();
this.shadow = this.attachShadow({ mode: 'closed' });
const css = `
:host(.box) { color:red }
`;
this.styles = document.createElement('style');
this.styles.innerHTML = css;
}
connectedCallback() {
const div = document.createElement('div');
div.innerHTML = `<code><${this.tagName.toLowerCase()}></code> connected!`;
this.shadow.appendChild(this.styles);
this.shadow.appendChild(div);
}
}
customElements.define('custom-element', CustomElement);
customElements.define('other-custom-element', OtherCustomElement);
<custom-element class="box"></custom-element>
<other-custom-element class="box"></other-custom-element>
现在的问题是:为什么我们可以简单地将:host
与任何其他选择器组合在一起,就拥有两种选择器。
这是为了避免在解析选择器时造成混淆和歧义,因为影子主机只能由特殊选择器选择。如果我们编写:host.foo
,浏览器将尝试将元素与.foo
和:host
匹配,但这会很棘手,因为.foo
只能与阴影树中的元素匹配,而{ {1}}可以走到外面,因此解析选择器以查找是否存在:host
以便考虑选择器的其余部分以匹配影子主机是很麻烦的。
使用:host
可使浏览器轻松解析选择器,而:host()
是:host
没有选择器的特殊情况。
注意:这与类似的伪类(例如
:host()
或:matches()
)的特殊性不同,它们仅采用其参数的特殊性。这是因为:not()
肯定是自己选择一个元素,就像“正常”的伪类一样;出于语法原因,它需要一个选择器参数 (我们不能说:host.foo匹配,但.foo不匹配),但在其他方面与只使用:host后跟一个选择器相同。 / p>
请注意,我们不能说:host
匹配,但是:host.foo
不匹配