再来週くらいにアドベントカレンダーでも似たようなこと書くんだけどあっちはちょっとお行儀よく書かなきゃいけないのでこっちには殴り書きという感じで今思ってることを書く
登場人物
vdom
純粋なDartによる仮想DOM実装。diff/patchは型のお陰で速いし、virtual-dom
でできることは出来る。作者のlocalvoid氏は後でまた出てくるんだけど仮想DOM廃人っぽい。Dartでもjsでも仮想DOMのことならなんでも知ってそう。
Liquid
↑のlocalvoid氏が作ったvdomによるUIフレームワーク。
React-dart
その名の通りReact.jsのDartラッパー。ポーティングではない。内部でReact.jsを呼んでる。
vdomではDartとDOMの距離が遠すぎる
仮想DOMのイベントリスナにDart側の関数を直接渡せない構造なのが最高にクソ。
VElement("button", attributes: { "onclick" : onclick() });
たったこれだけのことができない。実際にonclickイベントをDart側で受け取ろうとすると、追加するDOM要素にidやkeyを振って、ビュー初期化後に由緒正しいdocument.querySelector()
でHtmlElement要素引っ張りだして、onClickイベントにリスナー噛ませるか、"onclick"属性にonclick()
なりjsの関数呼び出すようにして、Dart側でdart:js使ってcontext["onclick"] = onClick
みたいに無理やりJsObjectねじ込むしかない。
前者は仮想DOMがpatchされて実DOMに要素が存在している状態じゃないとnullなのでリスナー挿せない。後者はJsObjectになってしまうので複雑になると処理追えない。
しかし普通に「仮想DOMだ~わ~い」できる。アドベントカレンダーにはサンプルコードみたいなの上げる。実用には耐えない。
Liquidだとちょっとマシ
https://github.com/localvoid/liquid/blob/master/example/todo/todo.dart#L32
Liquidが実装しているComponentというシステムなら割とDart側で書けるのでよい。イベントリスナも親が一任してイベントを受け取って、それを各要素にパターンマッチで振り分けていく形なので実DOMが存在するかどうかは関係ない。現実的。
Liquidはdart:mirrors使ってる
でもDart側で全部やろうとするとやっぱり無理があるっぽくて、リフレクション使ってる。なのでdart2jsするとAngularと同じでクッソビルド遅いしクッソでかくなる。
現実解はReact-dartっぽい
https://github.com/cleandart/react-dart/blob/master/example/react_test_components.dart#L31
React.jsに乗っかってるのでReact.jsが速くなれば速くなるし、書きやすそうでもある。ドキュメントやノウハウもjsの方と共通で通るので情報が無くて困るってこともあんまりない(はず)。
どうなんこれって感じのところもある
https://github.com/cleandart/react-dart/blob/master/lib/react.dart#L19
勝手にbind
とかいう関数をComponentクラスに追加してる。中身はsetStateのラッパーで、単なるシンタックスシュガーなんだけど、なんかモニョる。どうなんこれ
あと、React-dartはクライアントとサーバーどっちで動かすかみたいなところも選べる。Reactをサーバーサイドで動かすのってあんまり聞いてないけどアンテナ低いだけかな。
結論:JSXほしい
Liquidの文字列指定は嫌だし、
new VElement("div")(new VElement("h1")("Hello World"));
React-dartの関数化もコードがネスト地獄る原因である
div({}, h1({}, "Hello World"));
JSX Harmony欲しすぎる