WebLog

Web Componentsで子要素を取得したい

2022/11/12 10:01

Web Component で子要素を取得するには slot を使おう

Web Components で子要素を取得するには<slot>を使う

ElemntWithChildren.ts
1class ElementWithChildren extends HTMLElement {
2 connectedCallback() {
3 const shadow = this.attachShadow({ mode: "open" });
4 shadow.innerHTML = `
5 <div>
6 <slot></slot>
7 </div>
8 `;
9 }
10}
11
12customElements.define("element-with-children", ElementWithChildren);

ts をコンパイルして色々して

index.html
1<element-with-children>
2 <p>子要素だぞ</p>
3</element-with-children>

みたいにするとブラウザには dom って出る

開発者ツールから DOM を見てみると dom っていう変な感じになってる

slot に名前をつけよう

slot に name 属性をつけると、対応するところに挿入してくれる

UserCard.ts
1class UserCard extends HTMLElement {
2 connectedCallback() {
3 const shadow = this.attachShadow({ mode: "open" });
4 shadow.innerHTML = `
5 <div>
6 Name: <slot name="username"></slot>
7 </div>
8 <div>
9 Name: <slot name="birthday"></slot>
10 </div>
11 `;
12 }
13}
14
15customElements.define("user-card", UserCard);
index.html
1<user-card>
2 <span slot="username">John Smith</span>
3 <span slot="birthday">01.01.2001</span>
4</user-card>

connectedCallback 内では this.innerHTML で子要素を取得するのはやめよう

connectedCallback 内では innerHTML で子要素を取得するのは多分あまりよくない

これは以下のような理由から:

DOM は親要素 → 子要素の順にレンダリングされる

1<parent>
2 <child></child>
3</parent>

という構成だったら parent のレンダリングは child より先になる

connectedCallback は要素が DOM に挿入されたタイミングで走るけど、そのタイミングでは子要素がまだ作成されていない

1<script>
2 customElements.define(
3 "user-info",
4 class extends HTMLElement {
5 connectedCallback() {
6 alert(this.innerHTML); // connectedCallbackが走るタイミングではinnerHTMLは空
7 }
8 }
9 );
10</script>
11
12<user-info>John</user-info>

setTimeout とかで子要素の作成を待つこともできるけど、それだったら素直に slot を使った方がいい

参考

Shadow DOM スロット, コンポジション
Shadow DOM スロット, コンポジション

Shadow DOM スロット, コンポジション

最新の投稿