exportparts

**exportparts** 全域性屬性 允許你透過匯出其 part 名稱來選擇和設定巢狀 影子樹 中存在的元素的樣式。

影子樹是一個隔離的結構,其中識別符號、類和樣式無法被屬於常規 DOM 的選擇器或查詢訪問。有兩個 HTML 屬性可以應用於影子樹元素,它們允許從外部目標 CSS 樣式到影子樹:partexportparts

全域性 part 屬性使影子樹元素對其父 DOM 可見。part 名稱用作 ::part() 偽元素的引數。透過這種方式,你可以從影子樹外部應用 CSS 樣式到影子樹中的元素。但是,::part() 偽元素僅對父 DOM 可見。這意味著當影子樹巢狀時,這些部分對除了直接父級之外的任何祖先都是不可見的。exportparts 屬性解決了此限制。

exportparts 屬性允許影子樹部件在影子 DOM 外可見。這個概念被稱為“匯出”。exportparts 屬性放置在元素的影子宿主上,即影子樹所附加的元素。此屬性的值是一個以逗號分隔的 part 名稱列表,這些名稱存在於影子樹中。這些名稱可供當前結構外部的 DOM 使用。

html
<template id="ancestor-component">
  <nested-component exportparts="part1, part2, part5"></nested-component>
</template>

匯出 part 時,可以選擇為該部件分配不同的名稱,如下面的程式碼片段所示。exportparts 屬性的值實際上是一個逗號分隔的部件名稱對映列表。因此,上面程式碼片段中的 exportparts 屬性等效於 exportparts="part1:part1, part2:part2, part5:part5,表示每個 part 都以相同的名稱匯出。在每個對映中,第一個字串指定影子樹中部件的名稱,第二個字串指定部件在外部公開的名稱。

html
<template id="ancestor-component">
  <nested-component
    exportparts="part1:exposed1, part2:exposed2"></nested-component>
</template>

示例

基本元件

為了演示如何使用 exportparts 來啟用對巢狀元件內部件的目標定位,我們將建立一個元件,然後將其巢狀在另一個元件中。

HTML

首先,讓我們建立一個卡片元件,然後用另一個元件將其包裹起來。我們還使用了我們建立的新元素,使用純文字作為內容填充插槽。

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 元件。

js
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> 影子樹的部分進行樣式設定。

css
::part(body) {
  color: red;
  font-style: italic;
}

結果

巢狀元件

繼續上面的 <card-component> 示例,我們透過將 <card-component> 包裹在另一個元件中來建立一個巢狀元件;在本例中,是 <card-wrapper> 元件。然後,我們使用 exportparts 屬性匯出要使其能夠從元件的影子樹外部進行樣式設定的巢狀元件的部件。

HTML

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> 用於比較。

html
<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

js
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> 中巢狀時進行定位。

css
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)。

html
<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

js
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> 的部件時,我們只能透過其公開的部件名稱來為匯出的部件設定樣式。

css
/* 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

瀏覽器相容性

BCD 表格僅在瀏覽器中載入

另請參閱