ボタン

最初の例はインクリメントやデクリメントを行うカウンタの作成です。

以下にプログラムの全文を掲載しました。青い"Edit"ボタンをクリックして、オンラインエディタでいじってみましょう。ボタンの文字を書き換えてみてください。今すぐ青いボタンをクリック!

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



-- MAIN


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 "+" ]
    ]

コードを少しいじってみたことで、疑問を持ったかもしれませんね。このmainという値は何をしているのだろうか?どのようにして異なるパーツを組み合わせているのだろうか?と。コードを見ながら説明していきましょう。

Note: ここのコードは型注釈型エイリアスカスタム型を使用しています。この節のポイントはThe Elm Architectureの雰囲気をつかむことなので、これらはもう少し後で取り上げます。もしこういった面で行き詰まっているならば上記の節を覗いてみることをおすすめします!

Main

mainはElmでは特別な値で、画面に何を表示するかを記述します。この例では、アプリケーションをinitで初期化して、view関数ですべてを画面に表示し、ユーザーからの入力をupdate関数に渡します。これがプログラムの大まかな概要だと考えてください。

モデル

Elmでは、アプリケーションの状態をプログラムが扱える形にするモデル化が非常に重要です。モデルのポイントは、アプリケーションに関する情報を全てくまなくデータとして表現できるようにすることです。

カウンターを作るためには、増えたり減ったりする数を把握しておく必要がありますね。このケースでは、モデルが本当に小さなものになります。

type alias Model = Int

現在のカウントを把握しておくためにはInt型の値だけが必要です。これは初期値で確認できます。

init : Model
init =
  0

初期値はゼロで、各ボタンを押すと増えたり減ったりします。

View

これでモデルが用意できましたが、モデルの内容を画面に表示するにはどうすればいいでしょうか?それはview関数の役割です。

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

このviewという関数はModelを引数として受け取り、HTMLを出力します。ここでは、マイナスボタン、現在のカウント、プラスボタンを表示させることになります。

各ボタンにonClickハンドラーがあることに注目してください。クリックするとメッセージを生成するということです。つまりこのプラスボタンはIncrementメッセージを生成しています。メッセージを生成するとはどういうことでしょうか、そして生成されたメッセージはどこに行くのでしょうか?update関数に行きます!

Update

update関数は、各種イベントで生成されたメッセージをきっかけとして、Modelが各場面でどのように変化するかを記述するものです。

たとえば今回の例では、update関数は以下のように定義されている2つのメッセージを受け取る可能性があります。

type Msg = Increment | Decrement

それでは、メッセージを受信したとき何をすべきかを update 関数にそのまま記述しましょう。

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

    Decrement ->
      model - 1

Incrementメッセージを受け取ったらモデルをインクリメントし、Decrementメッセージを受け取ったらデクリメントします。

つまり何かメッセージを受け取るたびにupdateに渡して実行して新しいモデルを取得します。次にviewを呼び出して新しいモデルを画面にどう表示するか計算します。これがその後も繰り返されていきます!つまり、view によって表示された画面でユーザーが何か操作を行うとまたメッセージが生成され、それをupdate関数が受け取ってモデルを更新(update)し、viewがそのモデルを元にまた画面を表示(view)します。

全体像

これでElmのプログラムのすべてのパーツを見たわけですが、先ほど見た図のどこにどれが対応するかを整理してみると、もう少しわかりやすいかもしれません。

The Elm Architectureの図

Elmは初期値を画面に描画することから始まります。そこから以下のループに入ります。

  1. ユーザーからの入力を待ちます
  2. updateにメッセージを送ります
  3. 新しいModelを生成します
  4. view関数を呼び出して新しいHTMLを取得します
  5. 画面上に新しいHTMLを表示します
  6. 繰り返します!

これがThe Elm Architectureの本質です。これから見るすべての例は、この基本的なパターンにわずかなバリエーションを加えたものになります。

演習: カウンターをゼロにリセットするボタンを追加してみましょう

  1. ResetバリアントをMsg型に追加します
  2. update関数にResetの分岐を追加します
  3. view関数にボタンを追加します

このサンプルはこちらのオンラインエディタで編集できます。

これがうまくいったら、10ずつ増えるボタンを追加してみてください。

results matching ""

    No results matching ""