elmでやってみるシリーズ7: elm-htmlでTwitter Bootstrapを適用
Elmでやってみるシリーズ7: elm-htmlでTwitter Bootstrapを適用。
つい先日、「Blazing Fast HTML」と銘打って、elm-htmlライブラリが公開されました。これはElmでDOMツリーを構築・更新するための低レベルライブラリであり、Virtual DOMという技術を使っているので非常に画面更新速度が速いそうです。SPA(Single Page Application)ではDOMの更新速度が重要になりますが、Elmは純粋関数型・イミュータブルデータなのでそのことを利用してさらに効率良く実装できるそうな。
従来、ElmはCSSとの連携はあまり重視されておらず、「ElmはCanvasを使ったアニメーションが得意」とされてきましたが、現代的な見た目のHTMLベースのアプリも自在に開発できるようになる、という道筋の第一歩なわけです。まだ未成熟ですがね。
個人的にTwitter BootstrapなどのCSSフレームワークとElmとの連携に興味があったので、今回試してみました。
やったことは以下のとおり。
- elm-getでelm-htmlをインストール
- elm-get install evancz/elm-html 0.1.2
- HtmlTest.elmを作る(後述)
- 以下のように--only-jsオプションを付けてelmコードをコンパイル。なお、--only-jsを使用する場合、呼び出すためにモジュール名が必要なので冒頭でmodule宣言が必要になる。
- elm --make --only-js HtmlTest.elm
- Twitter Bootstrapを使用するindex.htmlをこちらの「Embed in HTML」を見て適当につくる。index.htmlの内容はこちらを表示してビューソースしてみてください。
- index.htmlとHtmlTest.jsをgithub pagesにpush。
処理の内容としては、マウスのX座標、Y座標の過去10個分をテーブルにして表示するというもの。
コード(HtmlTest.elm)は以下のとおり。
module HtmlTest where -- --js-onlyをする場合モジュール宣言は必須 import Html (..) import Mouse -- マウス座標データを一行分の<tr>に変換 data2line : (Int,Int) -> Html data2line (x,y) = node "tr" [] [] [ node "td" [] [] [text <| show x] , node "td" [] [] [text <| show y] ] -- テーブルを作る tbl : [(Int,Int)] -> Html tbl dat = node "table" ["className" := "table table-striped table-bordered table-condensed"] [] [ node "thead" [] [] [ node "tr" [] [] [ node "th" [] [] [text "Mouse X"] , node "th" [] [] [text "Mouse Y"] ] ] , node "tbody" [] [] (map data2line dat) ] -- アンカータグによるリンクを作るユーティリティ関数 linkTo txt url = node "a" ["href":=url] [] [text txt] -- ボタンのように装飾をしたリンクを作るユーティリティ関数 buttonLinkTo txt url = node "a" ["href":=url,"className":="btn btn-primary btn-lg"] [] [text txt] -- 画面を作る body : [(Int,Int)] -> Html body dat = node "div" ["className":="navbar navbar-default navbar-fixed-top"] ["padding-top":= px 10] [ node "div" ["className":="container"] [] [ node "div" ["className":="jumbotron"] [] [ node "h1" [] [] [ text "Elm/Twitter Bootstrap" ] , node "p" [] [] [ "Elm-html" `linkTo` "https://github.com/evancz/elm-html" , text "で" , "Twitter bootstrap" `linkTo` "http://getbootstrap.com/" , text "連携しています。"] , node "p" [] [] [ "もっと学ぼう" `buttonLinkTo` "http://elm-lang.org/" , "ソースコード" `buttonLinkTo` "HtmlTest.elm" ] ] , tbl dat ] ] -- 画面を表示する display : [(Int, Int)] -> Element display list = body list |> toElement 200 200 -- マウス座標のシグナル値(x,y)をliftして与えて画面を表示する main : Signal Element main = display <~ foldp (\it acc -> take 10 (it :: acc)) [] Mouse.position
気づいたこと
- elm-htmlはGroovyのマークアップビルダーみたいなもの。
- elm-htmlの出力はHtml(DOM)であり、それを変更する手段は提供されていない。なのでコード的には毎回全体を何も考えずに宣言的に生成する。しかし、Elmが完全に純粋であることも利用して、Vitual DOMを通じて、実DOMに対して最低限の差分のみが効率良く適用されるという話。
- elm-htmlの記述はHTMLと一対一対応で、冗長度が高いが、elm-htmlの位置付けは、より高機能でより抽象度の高いライブラリ作成の基盤になるための低レベルライブラリ、というものなのでこれはこれで良い。
- elm-htmlはいわゆる非標準ライブラリであり、しかも--only-jsでHTMLと連携させるので、share-elmなどでは公開できない。なのでgithub-pagesを使用して公開してみた。
- --only-jsを前提とするとelm-serverでホットリロードできない。もしくはやりかたがわからない。
- elm-htmlのHtmlとGraphics.Input(.Fields)との連携・関係はまだ理解できていない。elm-htmlだけでhandleを使えるから、こっちで閉じてやるんだろうか。そうじゃないとしたらElementやfieldをHtmlに入れる仕組みが必要なはずだが。
- elm-htmlではcssも要素の属性も基本的には文字列でしかない。本来なら強い型付けをして欲しいものですが、将来開発されるであろうelm-html上に構築される何かに期待。
- 合成と共有部分の切り出し、共有化、抽象化というプログラミングの本質的な強力さが現状でも享受できる。html,js,cssを使っていたWebアプリ開発暗黒時代の夜明け
- Elmで外付けスタイルシートを定義することはできない。本来はElmがLESSやSassの代替になって欲しいものである。*1
- CSSクラスの指定は「"className":=」、floatは「cssFloat」とするらしい。このような違いはJavaScriptでDOMをいじる場合と同様らしい。
関連エントリ
「Elmでやってみる」シリーズのまとめエントリ - uehaj's blog
- 作者: Miran Lipovača,田中英行,村主崇行
- 出版社/メーカー: オーム社
- 発売日: 2012/05/23
- メディア: 単行本(ソフトカバー)
- 購入: 25人 クリック: 580回
- この商品を含むブログ (67件) を見る
- 作者: Miran Lipovaca
- 出版社/メーカー: オーム社
- 発売日: 2012/09/21
- メディア: Kindle版
- 購入: 4人 クリック: 9回
- この商品を含むブログを見る