Closed6
shawdow DOM / Web Component とは
軽く読んだ感じ
- HTMLのコードをカプセル化して、他のHTMLと分離したもの
- shadow化することで、shawdow DOM外で定義したcssの影響を受けなくなる。
jsでは特定のHTMLエレメントにアタッチして、shadow DOMを作れる。
const host = document.querySelector("#host");
const shadow = host.attachShadow({ mode: "open" });
const span = document.createElement("span");
span.textContent = "I'm in the shadow DOM";
shadow.appendChild(span);
HTMLでは<template>
タグで囲む
<div id="host">
<template shadowrootmode="open">
<span>I'm in the shadow DOM</span>
</template>
</div>
- shawdow DOMはWebコンポーネント(Web Components)とよばれる技術群のひとつっぽい
- 見た感じ、Vueでよくある
<slot>
、<template>
がweb標準で使えるようになったっぽい? - ちょっとあとで触ってみる
shadow DOMの使い方
パターン1 : js内で作った要素をアタッチ
- shadow DOMのスイッチをONにして、js内で作った要素をアタッチ
- shadow DOMスイッチをONにすると、元々の要素は表示されなくなる。
- shadow DOM内で設定したcssはshadow DOMの外の要素には影響を及ぼさない(scoped CSSになっている)
<p>shadowCSSが適用されない</p>
<div id="my-test">
<p>Test</p>
</div>
<script>
const testHost = document.getElementById("my-test")
// shadow DOMをアタッチ
const testHostShadow = testHost.attachShadow({ mode: "open" });
// shadow DOMにstyleをアタッチ
const p = document.createElement("p");
const style = document.createElement("style");
style.textContent = "p { color: red; }";
// shadow DOMにshadow DOMをセットする。
testHostShadow.appendChild(style);
p.innerHTML = "<p>上書きされた</p>";
p.style = "p { color:red; }"
testHostShadow.appendChild(p);
</script>
表示するとこんな感じ
<p>Test</p>
は上書きされたので表示されない。
パターン2 : template要素をアタッチ
- template要素は書くだけでは実際には画面上に表示されない
-
template.content.cloneNode(true)
みたいにすると表示される。 - template要素を定義しておいて、それをshadow DOMにアタッチするときに
template.content.cloneNode(true)
にする。 - shadow DOMで上書きされる要素内 の子要素で、
slot
属性を指定した要素は、テンプレート内で同じ名前を持つ<slot>
要素に置換される。
<template id="my-template">
<style>
p {
font-weight: bold;
}
</style>
<slot name="message"></slot>
<p>shadow DOM で上書きした要素</p>
</template>
<div id="my-host">
<p>shadow DOMに上書きされて表示されないようそう</p>
<p slot="message">Slotが差し込まれる</p>
</div>
</body>
<script>
// shadow DOM を使ってtemplate要素をアタッチ
const myHost = document.getElementById("my-host");
const myHostShadow = myHost.attachShadow({ mode: "open" });
const template = document.getElementById("my-template");
myHostShadow.appendChild(template.content.cloneNode(true));
</script>
<style>
p {
text-decoration: underline;
}
</style>
表示するとこんな感じ
shadow DOMで上書きされる要素内 の子要素で、slot
属性を指定した要素が差し込まれている。
カスタムエレメント
- カスタムエレメントの定義において
<template>
とshadow DOMを使うことが多いらしい - 確かに、カスタムエレメントの定義にすごく便利そう
<style>
my-song-list {
display: flex;
gap: .5rem;
}
my-song {
border: 1px solid #999;
padding: .2rem;
width: 12rem;
}
</style>
<template id="my-template">
<style>
.title {
font-weight: bold;
}
</style>
<div class="title">
<slot name="title"></slot>
</div>
<div class="artist">(By <slot name="artist"></slot>)</div>
</template>
<my-song-list>
<my-song>
<span slot="title">Let it be</span>
<span slot="artist">The Beatles</span>
</my-song>
<my-song>
<span slot="title">Hotel California</span>
<span slot="artist">The Eagles</span>
</my-song>
<my-song>
<span slot="title">Stairway to Heaven</span>
<span slot="artist">Led Zeppelin</span>
</my-song>
</my-song-list>
<script>
const template = document.getElementById("my-template");
customElements.define("my-song",
class MySong extends HTMLElement {
constructor() {
super();
const shadowRoot = this.attachShadow({ mode: "open" });
shadowRoot.appendChild(template.content.cloneNode(true));
}
}
);
</script>
表示するとこんな感じ
サンプルコード
感想
生のHTMLでも結構Vueなどのフロントエンドフレームワークっぽいことができるんだなーという感じ。
フレームワーク使う必要ない時はこれを使ってみると良いかもしれない。
このスクラップは26日前にクローズされました