ボタン


サンプルコードをダウンロードするかオンラインエディタで試してください。


最初の例はインクリメントやデクリメントを行うシンプルなカウンタの作成です。プログラムすべてを一箇所にまとめて置けば読みやすいでしょう、用意しておきました!あとでひとつひとつ詳細をみていきます。

import Browser
import Html exposing (Html, button, div, text)
import Html.Events exposing (onClick)


main =
  Browser.sandbox { init = init, update = update, view = view }


-- MODEL

type alias Model = Int

init : Model
init =
  0


-- UPDATE

type Msg = Increment | Decrement

update : Msg -> Model -> Model
update msg model =
  case msg of
    Increment ->
      model + 1

    Decrement ->
      model - 1


-- VIEW

view : Model -> Html Msg
view model =
  div []
    [ button [ onClick Decrement ] [ text "-" ]
    , div [] [ text (String.fromInt model) ]
    , button [ onClick Increment ] [ text "+" ]
    ]

これで全部です!

Note: この章は typetype alias 宣言を含みます。それら詳細は次章である で読むことができます。この時点で深く理解しておく必要はありませんが、読むことで理解の手助けになる場合はご自由に読んで下さい。

カウンタプログラムを白紙から書くとき、私はいつもモデルを考えることから始めます。カウンタを作るには、最低でも増えたり減ったりする数字を記録する必要があります。それではモデルに関するところだけ書き始めましょう!

type alias Model = Int

モデルができたら、次は時が経つとどのように数字が変わるのか定義していきます。私はUIから受け取るメッセージ群を定義することで書ける UPDATE の部分からいつも始めます。

type Msg = Increment | Decrement

上記のコードを見ると、ユーザがカウンタをインクリメントやデクリメントできることが明確に分かります。Msg型はそういった機能をデータとして記述します。これは重要なことです!それでは、メッセージを受信したとき何をすべきかを update 関数にそのまま記述しましょう。

update : Msg -> Model -> Model
update msg model =
  case msg of
    Increment ->
      model + 1

    Decrement ->
      model - 1

Incrementメッセージを受け取ったらモデルをインクリメントし、Decrementメッセージを受け取ったらデクリメントします。非常に簡潔な関数です。

よし、すべて順調ですね。次の問題ですが、どうやってHTMLを作成しそれを画面で表示しましょうか? Elmはelm/htmlというライブラリを持っており、これを使うと通常のElm関数としてHTML5のすべてを書き表せます:

view : Model -> Html Msg
view model =
  div []
    [ button [ onClick Decrement ] [ text "-" ]
    , div [] [ text (String.fromInt model) ]
    , button [ onClick Increment ] [ text "+" ]
    ]

注目すべき点は、view関数がHtml Msg値を返すことです。Html MsgMsgの値を生み出しうるHTMLのかたまりだということを意味しています。view関数の定義を見てもらうと、IncrementDecrementのメッセージを生み出すためにonClick属性が設定されているのが分かるでしょう。これらはupdate関数にそのまま入力され、アプリ全体を動作させます。

もうひとつの注目すべき点は、divbuttonは単なる通常のElm関数であることです。これらの関数は (1) 属性のリストと (2) 子ノードのリストを引数に取ります。HTMLのシンタックスとほんの少し異なるだけです。そこかしこに<>を置く代わりにElmでは[]を置きます。HTMLを読めるあなた方にとっては、この変化に慣れることは非常に容易でしょう。でも、どうしてHTMLとまったく同じ外観にしないのでしょう?その理由は、Elm関数を使うことでviewを組み立てるときにElm言語の力を最大限に引き出せるからです!重複したコードを関数にまとめられます。さらに、それを補助関数としてモジュールに追加し、他のview以外の関数と同じようにインポートして使えます。また、他のElmコードと同じテストフレームワークやライブラリを使えます。Elmが持つプログラミングの利点すべてをviewで100%活用できるのです。もしもHTMLとまったく同じ外観だったなら、重複したコードをまとめたりするためにはPugやMustacheといったテンプレートエンジンの機能を使ってどうにかする必要があったでしょう。しかし実際にはそんな苦労をする必要はありません、Elmの関数で表現できるので!

もう少し掘り下げます。view部分のコードはすべて宣言的に書かれます。Modelを受け取りHtmlを生成する、それだけです。書き手がDOMに直接触れる必要もありません。Elmはそれを隠してうまくやってくれます。こうすることでElmに最適化する裁量を十二分に与えることができ、その結果、全体のレンダリングを速くすることになります。少ないコードを書くだけでそのコードは速く動作するのです。抽象化によるすごい効果です!

このパターンはThe Elm Architectureの本質です。これから示すすべての例はこの基本パターンであるModel, update, viewを少し変えたものです。

練習問題: The Elm Architectureが優れていることの一つに、プロダクトに変更が必要な場合はとても簡単に拡張できることが挙げられます。あなたのプロダクトマネージャが"reset"機能を思い付いたとしましょう。新しいボタンはカウンタを0にリセットします。

この機能を追加するにはMsg型の実装部分にもどってもう一つの可能性のResetを追加しましょう。メッセージを受け取ったときに何をすべきかをupdate関数に記述して下さい。最後はviewにボタンを追加して下さい。

それでは、"reset"機能を実装してみましょう!

results matching ""

    No results matching ""