PureScript + Halogen でカスタムエレメント
先日 Halogen v5 が正式リリースされました1。早速ガイドを読んでみましたが、いろいろとわかりやすくなってていい感じです。
ところで、Halogen でアプリケーションを作るとページを丸ごとそのアプリケーションにするような形になります。ガイドで説明されているアプリケーションの実行方法でもそうなっています2。
新しく作るアプリケーションであればそれでいいのですが、JavaScript なアプリケーションを一部だけ置き換えて段階的に導入していくようなときにはちょっと困ります。そういう時に便利なのがカスタムエレメントなのですが、PureScript + Halogen でカスタムエレメントは使えるのでしょうか?
というわけでやってみました。
サンプルアプリ
サンプルとしてまず以下のコードがあるとします。
module Main where
import Prelude
import Effect (Effect)
import Halogen.Aff as HA
import Halogen.VDom.Driver (runUI)
import MyComponent (component)
main :: Effect Unit
main = HA.runHalogenAff do
body <- HA.awaitBody
runUI component unit body
ここでモジュールMyComponent
は別ファイルで定義されているものとします。これを JavaScript にトランスパイルしたもの(my-component.js)を HTML で読み込んでブラウザで表示するとbody
要素内末尾に Halogen アプリケーションが展開されます。
<!DOCTYPE html>
<head>
<script src="my-component.js"></script>
</head>
<body>
</body>
</html>
もともとbody
に書かれていた要素が削除されることはありませんが、このままでは展開される位置は固定されており複数個所に挿入したくなってもできません。
今回はこれをカスタムエレメントmy-component
に突っ込めないか実験してみます。うまくいけば以下のような感じで使えるようになるはずです。
<!DOCTYPE html>
<head>
<script src="my-component.js"></script>
</head>
<body>
<header>
ここは普通にHTML
</header>
<section>
<h1>セクション1</h1>
<my-component></my-component>
</section>
<section>
<h1>セクション2</h1>
<my-component></my-component>
</section>
<footer>
ここもただのHTML
</footer>
</body>
</html>
カスタムエレメントの作成
器となるカスタムエレメントを JavaScript で作ります。
class MyComponent extends HTMLElement {
connectedCallback () {
// カスタムエレメントの機能を定義する
}
}
customElements.define('my-component', MyComponent);
connectedCallback
メソッドで Halogen コンポーネントを呼び出せばよさそうです。
ここでmain
関数を見てみると、HA.awaitBody
でbody
要素を取得して、それを引数にしてrunUI
を実行しています。
main :: Effect Unit
main = HA.runHalogenAff do
body <- HA.awaitBody -- ★
runUI component unit body
ここを先ほど作ったカスタムエレメントを渡すように変更してやればいいと思われます。しかしカスタムエレメント自体はbody
要素とは違って最初から DOM にあるものではありませんので、JavaScript から引数で渡すしかないでしょう。main
関数が引数を持つというのはちょっと変な感じがしますが、こんな感じでしょうか。
import Web.HTML.HTMLElement (HTMLElement)
main :: HTMLElement -> Effect Unit
main = HA.runHalogenAff <<< runUI component unit
ここで引数の型をHTMLElement
としたのはrunUI
がそうなっているからです。カスタムエレメントはHTMLElement
クラスを継承しているのでそれっぽいですね。
これをビルドして output ディレクトリにモジュールができたとしまして、カスタムエレメント側での呼び出しは以下のようにしてみます。
const PS = require('./output/Main');
class MyComponent extends HTMLElement {
connectedCallback () {
PS.main(this)();
}
}
customElements.define('my-component', MyComponent);
これを parcel などを使ってブラウザで読み込める形にしてやれば出来上がりです。
結果
ブラウザで表示したらこうなりました。コンポーネントの中身として Halogen ガイド2にあるカウンターを使っています。
どうやらうまくいっているようです
まとめ
今回の実験で以下のことがわかりました。
- Halogen でカスタムエレメントは作れる
-
main
関数にも引数を設定できて、JavaScript から呼び出すことができる
おまけ
ちなみに実験してみた後で「PureScript Halogen customElement」で検索したら、そのものずばりなリポジトリがありました。
ソースを見てみたら今回実験で作ったようなカスタムエレメントの定義を、丸ごと FFI で PureScript にしたものといった感じです。
実際にカスタムエレメントを使いたいときはこちらのライブラリを使わせてもらうのがいいかも。ただし package-sets3 には含まれていないので、インストールするには手動でパッケージリストへの登録が必要です。
また Pursuit4 で CustomElement を検索すると purescript-webcomponents というパッケージが見つかります5。しかしこちらは使用例の記載がないため、どういうものなのかいまいちよくわかりません…。
Author And Source
この問題について(PureScript + Halogen でカスタムエレメント), 我々は、より多くの情報をここで見つけました https://qiita.com/amderbar/items/bd7088743ea2d1535983著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .