サーチ…


前書き

アプリケーションを構造化するための推奨される方法は、「Elm Architecture」と呼ばれています。

最も簡単なプログラムの構成要素はmodel更新されることがありますすべてのデータ、union型格納したレコードMsgプログラムがそのデータを更新方法を定義して、機能のupdateモデルとなりますMsg 、新たなモデルを返し、関数viewモデルを取り、ページに表示されるHTMLを返します。関数がMsg返すMsgに、Elmランタイムはそれを使用してページを更新します。

初心者向けプログラム

HTMLは主に学習目的のためにbeginnerProgram持っています。

beginnerProgramは、サブスクリプションまたは実行中のコマンドを処理できません。

DOMイベントからのユーザー入力のみを処理できます。

modelをレンダリングするためのviewと状態の変更を処理するupdate関数が必要です。

この最小限のbeginnerProgram例を考えてみましょう。

この例のmodelは、単一のInt値で構成されています。

update関数には、 modelに格納されているIntをインクリメントするブランチが1つしかありません。

viewはモデルをレンダリングし、クリックDOMイベントを添付します。

初期化とビルドでサンプルをビルドする方法を参照してください

import Html exposing (Html, button, text)
import Html exposing (beginnerProgram)
import Html.Events exposing (onClick)


main : Program Never
main =
    beginnerProgram { model = 0, view = view, update = update }


-- UPDATE


type Msg
    = Increment

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


-- VIEW


view : Int -> Html Msg
view model =
    button [ onClick Increment ] [ text ("Increment: " ++ (toString model)) ]

プログラム

あなたのアプリケーションが初期化のための外部データを必要としないとき、 programは良い選択です。

サブスクリプションとコマンドを処理することができるため、HTTP通信やJavaScriptを使用したinteropなど、I / Oを処理する機会が増えます。

初期状態は、モデルと共に起動コマンドを返すために必要です。

programの初期化には、 modelview 、およびupdateとともにsubscriptionsを提供する必要がありsubscriptions

型定義を参照してください:

program :
    { init : ( model, Cmd msg )
    , update : msg -> model -> ( model, Cmd msg )
    , subscriptions : model -> Sub msg
    , view : model -> Html msg
    }
    -> Program Never

最も簡単な方法を説明すると、 サブスクリプションを使用する方法は、JavaScriptを使用した単純なポート通信をセットアップすることです。

初期化し、 HTMLに組み込み / 埋め込みでサンプルをビルドする方法を参照してください

port module Main exposing (..)

import Html exposing (Html, text)
import Html exposing (program)


main : Program Never
main =
    program
        { init = init
        , view = view
        , update = update
        , subscriptions = subscriptions
        }


port input : (Int -> msg) -> Sub msg


-- MODEL


type alias Model =
    Int


init : ( Model, Cmd msg )
init =
    ( 0, Cmd.none )


-- UPDATE


type Msg = Incoming Int


update : Msg -> Model -> ( Model, Cmd msg )
update msg model =
    case msg of
        Incoming x ->
          ( x, Cmd.none )


-- SUBSCRIPTIONS


subscriptions : Model -> Sub Msg
subscriptions model =
    input Incoming


-- VIEW


view : Model -> Html msg
view model =
    text (toString model)
<!DOCTYPE html>
<html>
    <head>
        <script src='elm.js'></script>
</head>
    <body>
    <div id='app'></div>
    <script>var app = Elm.Main.embed(document.getElementById('app'));</script>
    <button onclick='app.ports.input.send(1);'>send</button>
</body>
</html>

フラグ付きプログラム

programWithFlagsは、 programとの違いが1つだけあります。

JavaScriptからの初期化時にデータを受け入れることができます:

var root = document.body;
var user = { id: 1, name: "Bob" };
var app = Elm.Main.embed( root, user );

JavaScriptから渡されたデータはFlagsと呼ばれます。

この例では、JavaScriptオブジェクトをユーザー情報とともにElmに渡していますが、フラグの型エイリアスを指定することをお勧めします。

type alias Flags =
    { id: Int
    , name: String
    }

フラグはinit関数に渡され、初期状態を生成します。

init : Flags -> ( Model, Cmd Msg )
init flags =
    let
        { id, name } =
            flags
    in
        ( Model id name, Cmd.none )

型シグネチャとの違いがわかるかもしれません:

programWithFlags :
    { init : flags -> ( model, Cmd msg )          -- init now accepts flags
    , update : msg -> model -> ( model, Cmd msg )
    , subscriptions : model -> Sub msg
    , view : model -> Html msg
    }
    -> Program flags

初期化コードはほとんど同じですが、これはinit関数だけが異なるためです。

main =
    programWithFlags
        { init = init
        , update = update
        , view = view
        , subscriptions = subscriptions
        }

親子通信の片方向

例は、コンポーネントの構成と、親から子への一方向のメッセージの受け渡しを示しています。

0.18.0

コンポーネントの構成は、 Html.App.mapメッセージのタグ付けに依存しHtml.App.map

0.18.0

0.18.0 HTML.App HTML に折りたたまれた

コンポーネントの構成は、 Html.mapしたメッセージのタグ付けに依存していHtml.map

初期化とビルドでサンプルをビルドする方法を参照してください

module Main exposing (..)

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


main =
    beginnerProgram
        { view = view
        , model = init
        , update = update
        }

{- In v0.18.0 HTML.App was collapsed into HTML
   Use Html.map instead of Html.App.map
-}
view : Model -> Html Msg
view model =
    div []
        [ Html.App.map FirstCounterMsg (counterView model.firstCounter)
        , Html.App.map SecondCounterMsg (counterView model.secondCounter)
        , button [ onClick ResetAll ] [ text "Reset counters" ]
        ]


type alias Model =
    { firstCounter : CounterModel
    , secondCounter : CounterModel
    }


init : Model
init =
    { firstCounter = 0
    , secondCounter = 0
    }


type Msg
    = FirstCounterMsg CounterMsg
    | SecondCounterMsg CounterMsg
    | ResetAll


update : Msg -> Model -> Model
update msg model =
    case msg of
        FirstCounterMsg childMsg ->
            { model | firstCounter = counterUpdate childMsg model.firstCounter }

        SecondCounterMsg childMsg ->
            { model | secondCounter = counterUpdate childMsg model.secondCounter }

        ResetAll ->
            { model
                | firstCounter = counterUpdate Reset model.firstCounter
                , secondCounter = counterUpdate Reset model.secondCounter
            }


type alias CounterModel =
    Int


counterView : CounterModel -> Html CounterMsg
counterView model =
    div []
        [ button [ onClick Decrement ] [ text "-" ]
        , text (toString model)
        , button [ onClick Increment ] [ text "+" ]
        ]


type CounterMsg
    = Increment
    | Decrement
    | Reset


counterUpdate : CounterMsg -> CounterModel -> CounterModel
counterUpdate msg model =
    case msg of
        Increment ->
            model + 1

        Decrement ->
            model - 1

        Reset ->
            0

Html.App.mapによるメッセージタグ付け

コンポーネントは独自のメッセージを定義し、放出されたDOMイベントの後に送信されます。 親子通信からのCounterMsg

type CounterMsg
    = Increment
    | Decrement
    | Reset

このコンポーネントのビューはCounterMsgタイプのメッセージを送信するため、ビュータイプシグネチャはHtml CounterMsgです。

親コンポーネントのビュー内でcounterViewを再利用できるようにするには、すべてのCounterMsgメッセージを親のMsg渡す必要があります。

この手法をメッセージタグ付けといいます

親コンポーネントは、子メッセージを渡すためのメッセージを定義する必要があります。

type Msg
    = FirstCounterMsg CounterMsg
    | SecondCounterMsg CounterMsg
    | ResetAll

FirstCounterMsg Incrementはタグ付きメッセージです。

0.18.0

counterViewにタグ付きメッセージを送信させるには、 Html.App.map関数を使用する必要があります。

Html.map FirstCounterMsg (counterView model.firstCounter)
0.18.0

HTML.Appパッケージv0.18.0 HTMLパッケージにv0.18.0v0.18.0

counterViewにタグ付きメッセージを送信させるには、 Html.map関数を使用する必要があります。

Html.map FirstCounterMsg (counterView model.firstCounter)

これは型シグネチャHtml CounterMsg -> Html Msg変更するので、親ビュー内でカウンタを使用し、親の更新関数で状態更新を処理することができます。



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow