💣
マインスイーパーのWeb Compornentを作った
「Webサイトのこの部分にマインスイーパーを配置したいな」
というニーズに答えるため、マインスイーパーのWeb Compornentを作った。
こういうのを埋め込める。
使い方
HTMLにこれを埋め込む。これだけ。
<script type="module">
import { mine_sweeper } from 'https://unpkg.com/mine-sweeper-tag@latest/dist/mine-sweeper.es.js';
customElements.define('mine-sweeper', mine_sweeper)
</script>
<mine-sweeper cols="10" bomb="10" beep />
技術解説
Web Compornents
こんな感じの独自タグを定義できる技術。
フレームワークを問わず利用できるので、たいへんポータビリティが高い。
<mine-sweeper cols="10" bomb="10" beep />
colsが盤面のサイズで、bombが爆弾の数、beepがクリア時のファンファーレを鳴らすかどうか。
Vue3
今回のマインスイーパーはVue3で作った。
以前Reactでマインスイーパーで作っていたのだけど、Vueは標準でWebCompornents出力に対応しているので移植した。
Composition APIとscript setupの記法はReactと考え方が似ているので移植は割りと簡単にできた。
Web Compornents化も以下の手順でできる。
-
***.ce.vue
というファイル名でVueコンポーネントを定義する
通常のVueコンポーネントとWebCompornentsで別々に作成するのは面倒で、通常のVueコンポーネントを作ってWebCompornentsでくるむ、というやり方をした。 -
***.ce.vue
で定義したコンポーネントをdefineCustomElementして、それをexport
苦労した点
- Web Compornentsに渡されるパラメータはTypeScriptの型チェックをすり抜ける
TypeScriptの型チェックはあくまでコンパイル時のチェックだけなので、数字の属性を持つWebCompornentsに文字列を渡してもエラーにならない。これにハマってしまった。数字同士の足し算をしていたつもりが文字列同士の足し算として解釈され、微妙に座標がずれるなんとも分かりづらいバグが発生した。 - 子コンポーネントのCSSが反映されない
WebCompornentsが子供としてVueコンポーネントを持つ場合、子コンポーネントの中のCSSが反映されない。工夫してコードを書けば反映されるらしいが、これフレームワーク側でなんとかして欲しいよなぁ。
おわりに
マインスイーパーってひさしぶりに遊ぶと面白いですよね。
npmでも配布しています。
Discussion