Suche…


Einführung

Die empfohlene Methode zur Strukturierung Ihrer Anwendungen lautet "Elm-Architektur".

Das einfachste Programm besteht aus einem model Datensatz alle Daten zu speichern , die aktualisiert werden können, ein Union - Typ Msg , die Möglichkeiten , um Ihr Programm definiert , dass die Daten aktualisiert, eine Funktion update , die das Modell und nimmt Msg und gibt ein neues Modell und eine Funktion view des nimmt ein Modell und gibt den HTML-Code zurück, den Ihre Seite anzeigen soll. Immer wenn eine Funktion eine Msg zurückgibt, wird sie von der Elm-Laufzeitumgebung zum Aktualisieren der Seite verwendet.

Einsteigerprogramm

Html hat ein beginnerProgram hauptsächlich für Lernzwecke.

beginnerProgram Abonnements nicht ausführen oder Befehle ausführen.

Es kann nur Benutzereingaben von DOM-Ereignissen verarbeiten.

Sie benötigen lediglich eine view zum Rendern des model und eine update , um update zu verarbeiten.

Beispiel

Betrachten Sie dieses minimale Beispiel für ein beginnerProgram .

Das model in diesem Beispiel besteht aus einem einzelnen Int Wert.

Die update hat nur einen Zweig, der das im model gespeicherte Int erhöht.

Die view rendert das Modell und fügt Klick DOM-Ereignis hinzu.

Informationen zum Erstellen des Beispiels finden Sie unter Initialisieren und Erstellen

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)) ]

Programm

program ist eine gute Wahl, wenn Ihre Anwendung keine externen Daten für die Initialisierung benötigt.

Es ist in der Lage, Subskriptionen und Befehle zu handhaben, was viel mehr Möglichkeiten für die Handhabung von E / A bietet, wie z. B. die HTTP-Kommunikation oder die Interaktion mit JavaScript.

Der Ausgangszustand ist erforderlich, um die Startbefehle zusammen mit dem Modell zurückzugeben.

Für die Initialisierung des program müssen subscriptions zusammen mit model , view und update bereitgestellt werden.

Siehe die Typdefinition:

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

Beispiel

Der einfachste Weg, um zu veranschaulichen, wie Sie Abonnements verwenden können, besteht darin, eine einfache Port- Kommunikation mit JavaScript einzurichten.

Informationen zum Erstellen des Beispiels finden Sie unter Initialisieren und Erstellen / Einbetten in 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>

Programm mit Flaggen

programWithFlags hat nur einen Unterschied zum program .

Es kann die Daten bei der Initialisierung von JavaScript akzeptieren:

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

Die von JavaScript übergebenen Daten werden Flags genannt.

In diesem Beispiel übergeben wir ein JavaScript-Objekt mit Benutzerinformationen an Elm. Es wird empfohlen, einen Typalias für Flags anzugeben.

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

Flags werden an die init Funktion übergeben und erzeugen den Ausgangszustand:

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

Sie können den Unterschied von der Typensignatur feststellen:

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

Der Initialisierungscode sieht fast gleich aus, da nur die init Funktion anders ist.

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

Einweg-Eltern-Kind-Kommunikation

Das Beispiel zeigt, wie die Komponentenzusammensetzung und die unidirektionale Nachricht von Eltern zu Kindern weitergeleitet werden.

0,18,0

Die Komponentenzusammensetzung Html.App.map auf dem Message-Tagging mit Html.App.map

0,18,0

In 0.18.0 HTML.App in HTML

Die Komponentenzusammensetzung Html.map auf dem Message-Tagging mit Html.map

Beispiel

Wie Sie das Beispiel erstellen, erfahren Sie unter Initialisieren und Erstellen

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

Nachrichten-Tagging mit Html.App.map

Komponenten definieren ihre eigenen Nachrichten, die nach ausgestrahlten DOM-Ereignissen gesendet werden, z. CounterMsg aus der Eltern-Kind-Kommunikation

type CounterMsg
    = Increment
    | Decrement
    | Reset

Die Ansicht dieser Komponente Nachrichten senden CounterMsg Typ, daher die Ansicht Typ Signatur ist Html CounterMsg .

Um counterView in der Ansicht der übergeordneten Komponente wiederverwenden zu können, müssen wir jede CounterMsg Nachricht durch die Msg übergeordneten CounterMsg .

Diese Technik wird als Message-Tagging bezeichnet .

Die übergeordnete Komponente muss Nachrichten zum Übergeben untergeordneter Nachrichten definieren:

type Msg
    = FirstCounterMsg CounterMsg
    | SecondCounterMsg CounterMsg
    | ResetAll

FirstCounterMsg Increment ist eine markierte Nachricht.

0,18,0

Um eine counterView zum Senden von mit Tags versehenen Nachrichten zu erhalten, müssen Sie die Funktion Html.App.map verwenden:

Html.map FirstCounterMsg (counterView model.firstCounter)
0,18,0

Das HTML.App Paket wurde in v0.18.0 im HTML Paket v0.18.0

Um eine counterView zum Senden von mit Tags versehenen Nachrichten zu erhalten, müssen Sie die Funktion Html.map verwenden:

Html.map FirstCounterMsg (counterView model.firstCounter)

Html CounterMsg -> Html Msg sodass der Zähler in der übergeordneten Ansicht verwendet werden kann und Statusaktualisierungen mit der Aktualisierungsfunktion des übergeordneten Html CounterMsg -> Html Msg können.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow