1. このページの目的
カスタム要素 v1: 再利用可能なウェブ コンポーネント | Web | Google Developers に載っているコードを試してみる。
2. デモその1
<button>
タグ (HTMLButtonElement
クラス) を拡張する。
コード
<!-- カスタムタグではなく <button>タグを使う -->
<button is="fancy-button">Fancy button!</button>
<button is="fancy-button" disabled>Fancy button!</button>
<!-- 以下の使い方はNG -->
<fancy-button disabled>Hello!</fancy-button>
- 実際はそれぞれのタグを <p> タグで囲んでいる。
class FancyButton extends HTMLButtonElement {
...
}
customElements.define('fancy-button', FancyButton, {extends: 'button'});
define()
の第三引数で元のタグ名を指定する。クラス名とタグ名は1対1対応ではないため、ここで指定しなければいけない。
実行結果
メモ
<fancy-button><fancy-button>
と書いてもボタンにならない。- もともと存在している
HTMLButtonElement
のようなクラスを拡張した場合は、もとのタグを使いis
属性を指定する必要があるようだ。
3. デモその2
connectedCallback()
を使って、コンテンツを上書きする。
※ 要素定義済みのコンテンツを追加するには、、Shadow DOM を使ったほうが良い。
コード
<x-foo-with-markup>
<b>I'm an x-foo-with-markup!</b>
</x-foo-with-markup>
customElements.define('x-foo-with-markup', class extends HTMLElement {
connectedCallback() {
this.innerHTML = "<i>I'm an x-foo-with-markup!</i>";
}
});
実行結果
4. デモその3
「未登録要素の事前スタイル設定(:not(:defined)
)」を試す。
コード
<style>
app-drawer:not(:defined),
app-div:not(:defined) {
background-color: #c7d7ff; /* 薄い青 */
color: orange;
}
app-drawer:defined,
app-div:defined {
background-color: #ffc7e0; /* pink */
color: blue;
}
</style>
<app-drawer></app-drawer>
<p>---------------</p>
<app-div>app-div</app-div>
- Shadow DOM の外でスタイルを指定している。
window.customElements.define('app-drawer', class extends HTMLElement {
constructor() {
super();
// Attach a shadow root to the element.
let shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.innerHTML = `
<style>
:host {
color: red;
background-color: #ffc7e0; /* pink */
}
/* 以下は効かない
app-drawer {
background-color: #ffc7e0;
}*/
</style>
<span>Hi!</span>
<p>Hello, <span>World!</span></p>
`;
}
});
:host
はカスタムタグ自体を表す。
実行結果
---------------
メモ
- カスタムタグ内のスタイルは、Shadow DOM の外側の定義が優先される。
- Shadow DOM 内のCSSのセレクタでは、カスタムタグ名は使えない。
- 定義がないカスタムタグには、
:not(:defined)
がマッチする。
3. 結論
- 既存の要素を拡張する場合は、
define()
の第三引数に注意する。