慣例的に<link rel="import" href="x-element.html">
な感じでロードされているけど、前提として、 HTMLImportsである必要はない 。何故ならば、Web Componentsを構成する4つの仕様はそれぞれ独立しているからである。だから、インポートを使わなくてもdocument.registerElement()
でカスタム要素の定義は出来るし、HTMLのひな形を使いたい場合に<template>
タグを使っても良い。
HTMLを部品として含む場合
HTMLやCSSを部品として含む場合は、<template>
タグや、ShadowDOMを駆使しながらパーツを構成していくので、HTMLファイルに書かざるを得ない。もちろん、JavaScriptだけで書けないこともないんだけど、本質ではない。
先日画像をスクロール同期的にロードする要素、 1000ch/lazyload-image を作ったけど、こちらはHTMLファイルではなく、単一のJSファイル。GitHubが作っている github/time-elements なんかも、time-elements.jsだけで構成されているけど、こういう場合は<link rel="import" href="x-element.html">
ではなく、<script src="x-element.js"></script>
で事が足りる。
他のWeb Componentsに依存している場合
<x-element>
が<y-element>
に依存している場合は以下のように、x-element.html
内でy-element.html
をインポートする。
<link rel="import" href="y-element">
<template id="tmpl">
<div>This is x-element!</div>
</template>
<script>
var XElementPrototype = Object.create(HTMLElement.prototype);
XElementPrototype.createdCallback = function () {
console.log(document.querySelector('#tmpl'));
};
window.XElement = document.registerElement('x-element', {
prototype: XElementPrototype
});
</script>
そのコンポーネントからの相対パスを得たい
これは @hokaccha 氏が詳しく書いているが、Web Componentsとして配布するときに、画像等のサブリソースを含む場合は一工夫が必要になる。
例えば<x-element>
というカスタムエレメントが以下のように、img
フォルダの配下にfoo.png
とbar.png
を含んだ構成とする。
- x-element
- x-element.html
- img
- foo.png
- bar.png
bower
なんかでインストールされればx-element
というフォルダごとダウンロードされて、いざインポートするときには<link rel="import" href="bower_components/x-element/x-element.html">
のようになる。
このとき、foo.png
とbar.png
を含むフォルダはbower_components/x-element/img
というパスになるけど、x-element.html
側で素直にimg/foo.png
と参照していると、インポート元のドキュメントルートからそのパスを辿ることになるので、上手く参照出来ない。
だからdocument.baseURI
を使って相対パスを得たいということになるが、この場合に、HTMLファイルでないとdocument.currentScript.ownerDocument.baseURI
と、x-element.html
からみたベースのURLを辿れない。URL
オブジェクトと組み合わせるとアレコレするときに幾分スマートかも。
<script>
var doc = document.currentScript.ownerDocument;
var imgRoot = new URL('img', doc.baseURI);
console.log(imgRoot.href);
// => bower_components/x-element/img
</script>
ネタに走った感あるけど、 https://github.com/1000ch/x-zangief は上記のようなパス解決をしている。