Elm Language
느릅 나무 건축술
수색…
소개
응용 프로그램을 구성하는 데 권장되는 방법은 '느릅 나무 건축술 (Elm Architecture)'입니다.
간단한 프로그램은 구성 model 업데이트 할 수있는 모든 데이터를 저장하는 기록 노동 조합 유형 Msg 프로그램이 데이터, 기능 업데이트 방법을 정의 update 모델과 소요 Msg 새로운 모델을 리턴을하고, 기능 view 있는 모델을 사용하고 페이지에 표시 할 HTML을 반환합니다. 함수가 Msg 반환 할 때마다 Elm 런타임은이를 사용하여 페이지를 업데이트합니다.
초급 프로그램
HTML 은 주로 학습 목적으로 beginnerProgram 가지고 beginnerProgram .
beginnerProgram 은 구독을 처리하거나 명령을 실행할 수 없습니다.
DOM 이벤트로부터의 사용자 입력 만 처리 할 수 있습니다.
model 을 렌더링하는 view 와 상태 변경을 처리하는 update 함수 만 있으면됩니다.
예
beginnerProgram 최소한의 예제를 고려하십시오.
이 예제의 model 은 단일 Int 값으로 구성됩니다.
update 함수에는 model 저장된 Int 를 증가시키는 하나의 분기 만 model .
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 은 초기화에 외부 데이터가 필요없는 응용 프로그램에 적합합니다.
구독 및 명령을 처리 할 수 있으므로 JavaScript 또는 HTTP 통신과 같은 I / O를 처리 할 수있는 기회가 더 많아집니다.
초기 상태는 모델과 함께 시작 명령을 반환하는 데 필요합니다.
program 을 초기화하려면 model , view 및 update 와 함께 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 과 단 하나의 차이점 만 program .
자바 스크립트에서 초기화시 데이터를 받아 들일 수 있습니다 :
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
}
한 가지 방법으로 부모 - 자식 커뮤니케이션
예제에서는 구성 요소 구성과 부모에서 자식으로의 단방향 메시지 전달을 보여줍니다.
구성 요소 구성은 Html.App.map 사용하여 메시지 태그 지정을 사용 Html.App.map
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 는 태그가 지정된 메시지입니다.
counterView 에서 태그가 추가 된 메시지를 보내려면 Html.App.map 함수를 사용해야합니다.
Html.map FirstCounterMsg (counterView model.firstCounter)
HTML.App 패키지는 붕괴되었다 에 HTML 에서 패키지 v0.18.0
counterView 에서 태그가있는 메시지를 보내려면 Html.map 함수를 사용해야합니다.
Html.map FirstCounterMsg (counterView model.firstCounter)
이렇게하면 형식 시그니처 Html CounterMsg -> Html Msg 되므로 부모보기 내부에서 카운터를 사용하고 부모 업데이트 기능으로 상태 업데이트를 처리 할 수 있습니다.