HTML exportparts 全局属性
exportparts 全局属性允许您通过导出其 part 名称来选择和样式化嵌套 Shadow Tree 中存在的元素。
Shadow Tree 是一个隔离的结构,其中标识符、类和样式无法通过属于常规 DOM 的选择器或查询访问。有两个 HTML 属性可以应用于 Shadow Tree 元素,它们可以从外部定位 Shadow Tree 的 CSS 样式:part 和 exportparts。
全局 part 属性使 Shadow Tree 元素对其父 DOM 可见。part 名称用作 ::part() 伪元素的参数。通过这种方式,您可以从 Shadow Tree 外部将其 CSS 样式应用于 Shadow Tree 中的元素。但是,::part() 伪元素仅对父 DOM 可见。这意味着,当 Shadow Tree 嵌套时,这些部分对于直接父级以外的任何祖先都是不可见的。exportparts 属性解决了此限制。
exportparts 属性使 Shadow Tree 的部分在 Shadow DOM 外部可见。这个概念被称为“导出”。exportparts 属性放置在元素的shadow host上,即 Shadow Tree 所附加的元素。此属性的值是 Shadow Tree 中存在的 part 名称的逗号分隔列表。这些名称可供当前结构外部的 DOM 使用。
<template id="ancestor-component">
<nested-component exportparts="part1, part2, part5"></nested-component>
</template>
导出 part 时,您可以选择为该部分分配不同的名称,如下面的代码片段所示。exportparts 属性的值实际上是 part 名称映射的逗号分隔列表。因此,上面的代码片段中的 exportparts 属性等同于 exportparts="part1:part1, part2:part2, part5:part5,表示每个 part 都以相同的名称导出。在每个映射中,第一个字符串指定 Shadow Tree 中部分的名称,第二个字符串指定该部分将在外部暴露的名称。
<template id="ancestor-component">
<nested-component
exportparts="part1:exposed1, part2:exposed2"></nested-component>
</template>
示例
基本组件
为了演示 exportparts 如何用于启用对嵌套组件内部分的样式设置,我们将创建一个组件,然后将其嵌套在另一个组件中。
HTML
首先,让我们创建一个我们将用另一个组件包装的卡片组件。我们还使用了我们创建的新元素,并用纯文本填充插槽作为内容。
<template id="card-component-template">
<style>
:host {
display: block;
}
</style>
<div class="base" part="base">
<div part="header"><slot name="header_slot"></slot></div>
<div part="body"><slot name="body_slot"></slot></div>
<div part="footer"><slot name="footer_slot"></slot></div>
</div>
</template>
<card-component>
<p slot="header_slot">This is the header</p>
<p slot="body_slot">This is the body</p>
<p slot="footer_slot">This is the footer</p>
</card-component>
JavaScript
我们使用 JavaScript 来定义上面 HTML 中定义的 Web 组件
customElements.define(
"card-component",
class extends HTMLElement {
constructor() {
super(); // Always call super first in constructor
const cardComponent = document.getElementById(
"card-component-template",
).content;
const shadowRoot = this.attachShadow({
mode: "open",
});
shadowRoot.appendChild(cardComponent.cloneNode(true));
}
},
);
CSS
我们使用 ::part 伪元素来样式化 <card-component> Shadow Tree 的部分
::part(body) {
color: red;
font-style: italic;
}
结果
嵌套组件
在上面的 <card-component> 示例的基础上,我们通过将 <card-component> 包装在另一个组件中来创建一个嵌套组件;在这种情况下,是 <card-wrapper> 组件。然后,我们导出嵌套组件中那些我们希望从组件 Shadow Tree 外部进行样式设置的部分,使用 exportparts 属性。
HTML
<template id="card-wrapper">
<style>
:host {
display: block;
}
</style>
<card-component exportparts="base, header, body">
<slot name="H" slot="header_slot"></slot>
<slot name="B" slot="body_slot"></slot>
<slot name="F" slot="footer_slot"></slot>
</card-component>
</template>
我们包含一个 <card-wrapper> 自定义元素,以及一个 <card-component> 用于对比
<h2>Card wrapper</h2>
<card-wrapper>
<p slot="H">This is the header</p>
<p slot="B">This is the body</p>
<p slot="F">This is the footer</p>
</card-wrapper>
<h2>Card component</h2>
<card-component>
<p slot="header_slot">This is the header</p>
<p slot="body_slot">This is the body</p>
<p slot="footer_slot">This is the footer</p>
</card-component>
JavaScript
customElements.define(
"card-wrapper",
class extends HTMLElement {
constructor() {
super(); // Always call super first in constructor
const cardWrapper = document.getElementById("card-wrapper").content;
const shadowRoot = this.attachShadow({
mode: "open",
});
shadowRoot.appendChild(cardWrapper.cloneNode(true));
}
},
);
CSS
现在,我们可以直接定位 <card-component> 的部分,以及当它嵌套在 <card-wrapper> 中时,如下所示
h2 {
background-color: #dedede;
}
card-wrapper,
card-component {
border: 1px dashed blue;
width: fit-content;
}
::part(body) {
color: red;
font-style: italic;
}
::part(header),
::part(footer) {
font-weight: bold;
}
结果
注意:当嵌套时,footer 不是粗体,因为我们没有将其包含在 exportparts 中。
暴露映射的部分
为了重命名导出的部分,我们包含一个逗号分隔的映射部分列表,每个映射部分包含原始名称和导出名称,用冒号 (:) 分隔
HTML
我们使用重映射语法更新之前的 <card-wrapper> 自定义元素(从导出的部分列表中省略 body)
<template id="card-wrapper">
<card-component
exportparts="
base:card__base,
header:card__header,
footer:card__footer
">
<span slot="header_slot"><slot name="H"></slot></span>
<span slot="body_slot"><slot name="B"></slot></span>
<span slot="footer_slot"><slot name="F"></slot></span>
</card-component>
</template>
JavaScript
customElements.define(
"card-wrapper",
class extends HTMLElement {
constructor() {
super(); // Always call super first in constructor
const cardWrapper = document.getElementById("card-wrapper").content;
const shadowRoot = this.attachShadow({
mode: "open",
});
shadowRoot.appendChild(cardWrapper.cloneNode(true));
}
},
);
CSS
在从 <card-wrapper> 中定位 <card-component> 的部分时,我们只能通过其暴露的部分名称来样式化导出的部分
/* selects the exported parts name */
::part(card__header) {
font-weight: bold;
}
/* selects nothing: these part names were not exported */
::part(footer),
::part(body) {
font-weight: bold;
}
结果
规范
| 规范 |
|---|
| CSS 影子部分 # element-attrdef-html-global-exportparts |
浏览器兼容性
加载中…
另见
partHTML 属性<template>和<slot>HTML 元素::part和::slotted伪元素:host伪类ShadowRoot接口Element.part属性- 使用模板和插槽
- CSS 作用域模块