Web Componentsに触れる
Web Componentsに触れる:
一連のテクノロジーの主な中身
- HTML Templates
- HTML Imports
- Shadow DOM
- Custom Elements
これらを一つづつ、さらっと表面をなぞっていく
※見やすくするためにhtmlでは、html要素とhead要素を使っていません
再利用可能なHTML要素
index.html
この時点では、なにも表示されない
JSでtemplateをクローンしてbodyにappendChildする
main.js
template自体を表示させるんじゃなくて、いったんcloneして生成するのがキモ。
img src(unknow)になってるのでsrcをつけてみる
main.js
template要素.contentに対してquerySelectorする
外部HTMLを読み込む
foo.html
index.html
main.js
インポートしたfoo.htmlからh1を取り出してbodyにappendChildしている。
template.html
index.html
main.js
※import元のhtmlの名前空間(idやclass)にはスコープが生成されるが、styleはそうでないので注意
template.html
index.html
main.js
index.htmlにも、template.htmlのスタイルが適用される。
styleの名前空間を汚したくない!
→Shadow DOMで解決
カプセル化してくれるやつ
index.html
main.js
一見何の変哲もないが、
ShadowDOMは表示だけを担当し、JSから参照する場合は、元々の値が返される。
使いみちは?
→ShadowDOMはstyleを含めたスコープを持つ(カプセル化と言う)
ということで、
template.html
index.html
main.js
無事、styleの名前空間を分離することができた
タグを自作
いきなり、全部の合わせ技
template.html
index.html
main.js
2018/10/14時点ではブラウザの対応状況がマチマチなので注意
HTML ImportsとShadow DOMにいたっては草案(Working Draft: WD)段階
https://caniuse.com/#feat=template
https://caniuse.com/#feat=imports
https://caniuse.com/#feat=shadowdomv1
https://caniuse.com/#feat=custom-elementsv1
0. WebComponentsって?
Web Components は、再利用可能なカスタム要素を作成し、ウェブアプリの中で利用するための、一連のテクノロジーです。引用元:https://developer.mozilla.org/ja/docs/Web/Web_Components
一連のテクノロジーの主な中身
- HTML Templates
- HTML Imports
- Shadow DOM
- Custom Elements
これらを一つづつ、さらっと表面をなぞっていく
※見やすくするためにhtmlでは、html要素とhead要素を使っていません
1. HTML Templates
再利用可能なHTML要素index.html
<body> <template> <h1>Hello HTML Templates</h1> <img src=""> </template> <script src="main.js"></script> </body>
JSでtemplateをクローンしてbodyにappendChildする
main.js
const TEMPLATE = document.querySelector('template'); const CLONE = document.importNode(TEMPLATE.content, true); document.body.appendChild(CLONE);
template自体を表示させるんじゃなくて、いったんcloneして生成するのがキモ。
img src(unknow)になってるのでsrcをつけてみる
main.js
const TEMPLATE = document.querySelector('template'); TEMPLATE.content.querySelector('img').src = 'https://dummyimage.com/99'; const CLONE = document.importNode(TEMPLATE.content, true); document.body.appendChild(CLONE);
2. HTML Imports
外部HTMLを読み込むfoo.html
<h1>Hello HTML Imports</h1>
<body> <link rel="import" href="foo.html"> <script src="main.js"></script> </body>
const IMPORT = document.querySelector('link[rel="import"]').import; const HEADER = IMPORT.querySelector('h1'); document.body.appendChild(HEADER.cloneNode(true));
HTML TemplateをHTML Importsする
template.html<template> <h1>Hello HTML Templates from template.html</h1> <img src=""> </template>
<body> <link rel="import" href="template.html"> <script src="main.js"></script> </body>
//HTML imports const IMPORT = document.querySelector('link[rel="import"]').import; //HTML template const TEMPLATE = IMPORT.querySelector('template'); TEMPLATE.content.querySelector('img').src = 'https://dummyimage.com/99'; //クローンを作成してbodyに生やす const CLONE = document.importNode(TEMPLATE.content, true); document.body.appendChild(CLONE);
※import元のhtmlの名前空間(idやclass)にはスコープが生成されるが、styleはそうでないので注意
template.html
<template> <style> h1 { color: red; } </style> <h1>Hello from template.html</h1> </template>
<body> <h1>Hello from index.html</h1> <link rel="import" href="template.html"> <script src="main.js"></script> </body>
const IMPORT = document.querySelector('link[rel="import"]').import; const TEMPLATE = IMPORT.querySelector('template'); const CLONE = document.importNode(TEMPLATE.content, true); document.body.appendChild(CLONE);
index.htmlにも、template.htmlのスタイルが適用される。
styleの名前空間を汚したくない!
→Shadow DOMで解決
3. Shadow DOM
カプセル化してくれるやつindex.html
<body> <h1>Hello</h1> <script src="main.js"></script> </body>
const SHADOW = document.querySelector('h1').createShadowRoot(); SHADOW.textContent = 'Hello Shadow DOM';
一見何の変哲もないが、
ShadowDOMは表示だけを担当し、JSから参照する場合は、元々の値が返される。
使いみちは?
→ShadowDOMはstyleを含めたスコープを持つ(カプセル化と言う)
ということで、
HTML TemplateをHTML ImportsしてShadowDOMで出力する
template.html<template> <style> h1 { color: red; } </style> <h1>Hello from template.html</h1> </template>
<body> <h1>index.html</h1> <div id='for_shadow'></div> <link rel="import" href="template.html"> <script src="main.js"></script> </body>
//HTML imports const IMPORT = document.querySelector('link[rel="import"]').import; //HTML template const TEMPLATE = IMPORT.querySelector('template'); const CLONE = document.importNode(TEMPLATE.content, true); //Shadow DOM const SHADOW = document.querySelector('#for_shadow').createShadowRoot(); SHADOW.appendChild(CLONE); //DOMアクセス console.log(document.querySelector('#for_shadow').shadowRoot); console.log(document.querySelector('#for_shadow::shadow h1'));
無事、styleの名前空間を分離することができた
4. Custom Elements
タグを自作いきなり、全部の合わせ技
template.html
<template> <h1>Hello from template.html as x-card</h1> </template>
<body> <link rel="import" href="template.html"> <script src="main.js"></script> </body>
//Custom Elementsを定義 const card = class extends HTMLElement { connectedCallback() { //お約束 //html import const IMPORT = document.querySelector('link[rel="import"]').import; //html template const TEMPLATE = IMPORT.querySelector('template'); const CLONE = document.importNode(TEMPLATE.content, true); //Shadow DOM this.createShadowRoot().appendChild(CLONE); } }; //x-cardタグにcardクラスを登録 window.customElements.define('x-card', card); //bodyに生成 document.body.appendChild(new card()); ![](https://d2mxuefqeaa7sj.cloudfront.net/s_2DAEA40B10D7CD0BC867F66D74B2266921463141871BDD2BA2941A20F0A64C24_1539513878920_image.png)
5. ブラウザの対応状況
2018/10/14時点ではブラウザの対応状況がマチマチなので注意HTML ImportsとShadow DOMにいたっては草案(Working Draft: WD)段階
https://caniuse.com/#feat=template
https://caniuse.com/#feat=imports
https://caniuse.com/#feat=shadowdomv1
https://caniuse.com/#feat=custom-elementsv1
コメント
コメントを投稿