Поиск…


Вступление

Рекомендуемый способ структурирования ваших приложений называется «Elm Architecture».

Простейшая программа состоит из model записи , хранящего все данные , которые могут быть обновлены, тип союза Msg , который определяет пути ваша программа обновляет эти данные, функция update , которая принимает модель и Msg и возвращает новую модель, и функция view , которая берет модель и возвращает HTML, который отобразит ваша страница. Каждый раз, когда функция возвращает Msg , среда выполнения Elm использует ее для обновления страницы.

Программа для начинающих

Html имеет beginnerProgram основном для учебных целей.

beginnerProgram не может обрабатывать Подписки или выполняемые команды.

Он способен обрабатывать только пользовательский ввод событий DOM.

Это требует только view для отображения model и функции update для обработки изменений состояния.

пример

Рассмотрим этот минимальный пример beginnerProgram .

model в этом примере состоит из одного значения Int .

Функция update имеет только одну ветвь, которая увеличивает Int , сохраненную в model .

view отображает модель и присоединяется к событию DOM.

Посмотрите, как построить пример в Initialize and build

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 - хороший выбор, когда ваше приложение не требует каких-либо внешних данных для инициализации.

Он способен обрабатывать Subscriptions и Commands, что позволяет использовать больше возможностей для обработки ввода-вывода, таких как HTTP-связь или взаимодействие с JavaScript.

Начальное состояние требуется для возврата команд запуска вместе с моделью.

Для инициализации program потребуются subscriptions , а также model , view и update .

См. Определение типа:

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

пример

Самый простой способ проиллюстрировать, как вы можете использовать Подписки, - это настроить простую связь с портами с помощью JavaScript.

Посмотрите, как создать пример в Initialize и build / Embedding в 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 .

Он может принимать данные при инициализации из JavaScript:

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

Данные, переданные из JavaScript, называются флагами.

В этом примере мы передаем объект 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

0.18.0

В 0.18.0 HTML.App был HTML.App в HTML

Компонентный состав зависит от тегов сообщений с помощью Html.map

пример

Посмотрите, как создать пример в Initialise и build

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 был HTML.App пакет HTML в v0.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