如果你是编写Web Components的新手,Web Components组件中的:host选择器可能有点棘手和令人困惑。然而,不要害怕!在这篇文章中,我将介绍所有你可能使用:host选择器的不同情况!
视频教程:Web Components开发者必看:如何正确使用:host选择器_哔哩哔哩_bilibili
这篇文章是从我个人的英文博客翻译过来的:How to use web components :host selector?
让我们先来看看像下面这样的一个组件。
<fancy-button>
#shadow-root(open)
<button><slot></slot></button>
<just-a-spinner></just-a-spinner>
<style>/* will add css rules here to style this component */</style>
</fancy-button>
本例中的槽元素允许我们在网页中这样使用这个自定义元素。
<fancy-button>Click me</fancy-button>
一旦浏览器定义了这个自定义元素,文本 "Click me "将被视为我们槽元素的textContent。顺便说一下,槽元素默认为display: contents,所以你可以把按钮当作 "Click me "这个文本的父包。
现在,让我们进入主题 :host选择器。
1. 基础
/* valid rule */
:host {
display: flex;
}
/* invalid rule */
fancy-button {
display: flex;
}
在我们的自定义元素fancy-button的shadow root里面,我们不能使用fancy-button的CSS标签选择器来定位我们的自定义元素,因为shadow root里面的样式被封装了。这就是:host选择器发挥作用的地方。
有一点需要注意的是,自定义元素默认是一个内联元素。然而,我发现,大多数时候,默认的内联行为并不是我们真正想要的。
2. :host和class
如果我们想针对有visible类的fancy-button,我们需要在括号内添加visible,像这样。
<fancy-button class="visible">Click me</fancy-button>
3. :host和attribute
就像类一样,属性在作为选择器使用时也需要用括号括起来。例如,如果我们想选择所有带有theme="round "属性的按钮元素。
<fancy-button theme="round">Click me</fancy-button>
:host([theme="round"]) {
border-radius: 2em;
}
在某些情况下,我们可能希望用户能够定义我们的具有多个主题属性的按钮组件。
<fancy-button theme="round large">Click me</fancy-button>
作为一个组件作者,我们可以使用方便的~CSS操作符来锁定特定的主题属性。这个操作符可以选择具有指定属性的元素,其值包含一个给定的单词,并以空格为界。
:host([theme~="round"]) {
border-radius: 2em;
}
:host([theme~="large"]) {
font-size: 1.2rem;
}
/* or want to styles button differently */
:host([theme~="round"]) button {
/* styles here */
}
:host([theme~="large"]) button {
/* styles here */
}
4. 如何处理 :hover :focus :focus-within状态?
对于像 :hover, :focus 和 :focus-within 这样的元素状态,在作为选择器使用时,也需要用括号括起来。
:host(:hover) {
background: white;
}
:host([theme="purple"]:hover) {
background: purple;
}
:host(:focus-within) {
border: 1px solid white;
}
:host([theme="purple"]:focus-within) {
border-color: purple;
}
5. 那么::before和::before的suedo-elements呢?
对于::before和::after这两个元素,在作为选择器使用时,需要在括号外。
:host::before {
content: attr(data-content);
}
:host([theme="purple"])::before {
border: 1px solid purple;
}