ブラウザ対応が着々と進んできて、 Web Components の利用が現実味を帯びてきました。
そんななか、ざっと Web Components のおさらいと vue-custom-element
に着目してみたいと思います。
Web Components とは?
- Custom Elements
- Shadow DOM
- HTML imports
- HTML Template
の4つの大きな仕様から構成される Web プラットフォーム API です。
Custom Elements
で自由にカスタム要素を生成することができ、 Shadow DOM
でカプセル化を促します。
Web Components の利用を簡潔に行うためのライブラリ Polymer なども存在しています。
これらの詳しい情報に関しては WEBCOMPONENTS.ORG にまとめられています。
Vue と Web Components の相性
Vue のテンプレート構文自体は HTML を拡張したような構文になっているので、Web Components はかなり親和性の高いものだと思います。
Custom Elements Everywhere でも、 Vue は満点評価になっています
Vue with Web Components
せっかくなので、Vue に Web Components を乗せてみました(DEMO)
ただ、 Web Components の現行の仕様の1つの HTML imports は ブラウザの実装状況 がよくなく、ES Modules ( HTML Modules ) に取って代わられるであろうとも云われています
(今回は ES Modules を利用していますので、Chrome などで閲覧願います!)
どちらもクリックをすると、カウントアップさせるようにしているのですが、
-
Vue Component : 通常通り
vue-loader
を利用した単一ファイルコンポーネント -
Web Components : ボタンの見た目だけは
Web Components
、クリックイベント発火時の処理に関しては Vue に任せるような形
にしています。
開発者ツールでソースを確認していただけると、作りが全然異なっていることがわかるでしょう。
見た目だけの薄い作りにしておくことで、万が一 Vue 以外のフレームワークなどでもコンポーネントを利用したい( Web Components 部分のみ流用する形 )となったときに、融通が利きやすそうです。
Vue.config.ignoredElements = [
'wc-button-red'
];
また、Vue のコンポーネントとして認識されないように、Web Components として登録しているコンポーネントを ignore 指定しておくことがポイントです。
Vue Costom Elements とは?
こちらは Vue コンポーネントのラッパーライブラリになります。
Web Components の Custom Elements 機能を利用(Polyfillも勿論あります)しており、Vueコンポーネントをカスタム要素として抽出・登録 をすることができます。
素の状態で利用したり、Vue.js 以外のコンポーネント指向フレームワーク(ライブラリ)などでも使用したりなどが可能になります(そんなユースケースはあまり存在しないかもしれませんが...)
vue-custom-elements に触れてみる
ここから先は特に DEMO を作成していません。
スクショを貼っているので、何となく雰囲気を感じていただければ...
Vueコンポーネントをカスタム要素に登録
button.vue
というコンポーネントがあったとして、 それを vce-button
というカスタム要素として登録してみます。
<template>
<button>{{text}}</button>
</template>
<script>
export default {
name: 'button',
data () {
return {
text: 'ボタンです'
}
}
}
</script>
<style lang="scss">
button {
font-size: 16px;
cursor: pointer;
color: #fff;
padding: 1em 2em;
background: royalblue;
}
</style>
import Vue from 'vue'
import vueCustomElement from 'vue-custom-element'
import Button from './components/button.vue'
Vue.use(vueCustomElement);
Vue.customElement('vce-button', Button); // ここで定義!!
<vce-button>
のカスタム要素としてレンダリングが行われていますね!
CSSの展開はいつも通り style-loader
での展開になるので、 scope
を付けてClass名をハッシュ値に変換しておいた方がよさそうです。
この辺は vue-loader
のお作法がそのまま活かされるようです。
ShadowDOM の利用
Optional で ShadowDOM を利用することもできます。
ShadowDOM を利用する場合は、 vue-loader
の <style>
要素部分は無視されます。
Vue.customElement('vce-button', Button, {
shadow: true,
shadowCss: `
button {
font-size: 16px;
cursor: pointer;
color: white;
padding: 1em 2em;
background: royalblue;
`
});
Props の利用
コンポーネント間は勿論のことですが、カスタム要素として登録する際に、その子どもにあたるコンポーネントに Props
を渡すこともできます。
<body>
<!-- props で suffix を渡す -->
<vce-button suffix="か?" />
<script src="./dist/build.js"></script>
</body>
<template>
<button>{{text}}{{suffix}}</button>
</template>
<script>
export default {
name: 'button',
props: {
'suffix': String,
},
data () {
return {
text: 'ボタンです'
}
}
}
</script>
Slot の利用
いつもの感覚で slot を利用することもできます。
<body>
<vce-button>
<span vue-slot="prefix">私は</span>
ボタンです
</vce-button>
<script src="./dist/build.js"></script>
</body>
<template>
<button>
<!-- いつもの事ながら、名前付きslotの初期値を入れておける -->
<slot name="prefix">これは!!!</slot><slot></slot>
</button>
</template>
Vue の UI ライブラリを入れてみる
ライブラリの DEMO のところを見てみると、
しれっと当然のように、Vue の UI ライブラリである Element が内包されたカスタム要素を作成していたりします。
原理的には、Vue のコンポーネントで有りさえすればどのような形でもカスタム要素は生成できるみたいです。
ただ、その分当たり前ですが JS のファイルサイズが跳ね上がるので、様子見ながらと云ったところでしょうか?
さいごに
Web Components が普及することで、 UI ライブラリの選択肢も Vue のものに限る必要がなくなってきますし、ライブラリ自体の製作者側の負担も減ってきそうです。
Web Components に触れる機会はこれからどんどん増えていくでしょうし、 Vue ももちろんですが今後の動向が気になるところですね!