descjop で遊ぼう day 11 : Omのコンポーネントで遊ぼう
ここのところ、descjopの話というよりはOmの話が続いていますが、実際の所、ClojureScriptでアプリケーションを作るということは、Electronのレイヤー、Node.jsのレイヤー、ClojureScriptのレイヤー、Clojureのビルドまわりの設定レイヤー、そしてフロントエンドライブラリに関するレイヤーといったそれぞれのレイヤーを適切に設計し、それらを協調させることでアプリケーションが動作するということであります。
さて、前回、ちょっとだけHello Worldをカスタマイズしました。
今回もちょこっとだけカスタマイズしてみます。
前回作成したサンプルは、ボタンを押すと、HTMLが変化するというものでした。
ただ、これはボタンも表示場所も含めて一つのルートコンポーネントに記述しており、拡張していくのには限界があります。
そこで、今回は、Omのコンポーネントを使って部品化を進めてみましょう。
コンポーネント向けの状態を定義
まず、app-state
へ、コンポーネント用向けに状態を追加しておきます。
下記のように変更してみてください。
(defonce app-state (atom {:message "Hello om world!"
:mini-component {:message ""}}))
:mini-component
というキーがマップに追加されています。この部分を更新するコンポーネントと、表示するコンポーネントを作ります。
最小コンポーネントをつくってみる
まずは、表示するコンポーネントから。
以下のコードを追加してみましょう。
(defn mini-component
"小さなOmコンポーネント"
[owner]
(om/component
(dom/p nil
(str (:message owner) "ミニミニコンポーネント!") )))
この関数はOmコンポーネントを返す関数で、おそらく最も小さいOmコンポーネントです。受け取ったカーソルにある:message
を表示する以外なにもしません。
om/component
というのは、Omで用意されているマクロで、実際には下記のように書いたのと同義になります。
(defn mini-component
"小さなOmコンポーネント"
[message owner]
(reify om/IRender
(render [this]
(dom/p nil
(str (:message message) "ミニミニコンポーネント!")))))
om/component
のコードは以下のように定義されています。
(ns om.core)
(defmacro component
"Sugar over reify for quickly putting together components that
only need to implement om.core/IRender and don't need access to
the owner argument."
[& body]
`(reify
om.core/IRender
(~'render [this#]
~@body)))
コンポーネントの配置
続いて、mount-root
を編集します。
(defn mount-root []
(om/root
(fn [state owner]
(reify om/IRender
(render [this]
(dom/div nil
(dom/h1 nil (:message state))
(dom/p {:className "my-message"} (:message state))
(om/build mini-component (:mini-component state))
(dom/button #js {:onClick (fn [e]
(om/transact! state :message (fn [] "World.")))
:className "press"}
"Hello")))))
app-state
{:target (. js/document
(getElementById "app"))}))
(om/build mini-component (:mini-component state))
が、追加されたコードになります。
om/build
は、コンポーネントを任意の場所に生成する関数です。第1引数には、IRender
やIRenderState
インターフェースを実装したインスタンスを返す関数を渡します。
つまり、Omのコンポーネントというのは、これらのインターフェースを実装したインスタンスを返す関数というわけです。
第2引数で、ここで、app-state
の:mini-component
以下をカーソルとして渡しているのがわかると思います。
これで、アプリケーションを実行すると、ミニミニコンポーネント!
と書かれたpタグ要素が出力されたのがわかると思います。
明日は、ボタンコンポーネントを作ります。
Colophon
- 編集長
- Greative GK. 原一浩 ( kara_d )
- 製版システム
- Clojure / Compojure / Ring / Enlive / markdown-clj / Jetty / MySQL
- Share this magazine!
- Follow designudge
- Follow @designudge