Elm - 命令



在前面的章節中,我們討論了 Elm 架構的各個元件及其功能。使用者和應用程式使用訊息相互通訊。

考慮一個示例,其中應用程式需要與其他元件(例如外部伺服器、API、微服務等)通訊以服務於使用者請求。這可以透過在 Elm 中使用命令來實現。訊息和命令不是同義詞。訊息表示終端使用者和應用程式之間的通訊,而命令表示 Elm 應用程式如何與其他實體通訊。命令是響應訊息觸發的。

下圖顯示了一個複雜的 Elm 應用程式的工作流程:

Workflow

使用者與檢視互動。檢視根據使用者的操作生成相應的訊息。更新元件接收此訊息並觸發一個命令。

語法

定義命令的語法如下所示:

type Cmd msg

檢視生成的訊息傳遞給命令。

示例

以下示例向 API 發出請求並顯示 API 返回的結果。

應用程式接受使用者輸入的數字,將其傳遞給 Numbers API。此 API 返回與該數字相關的知識。

應用程式的各個元件如下:

Http 模組

Elm 的 Http 模組用於建立和傳送 HTTP 請求。此模組不是核心模組的一部分。我們將使用 Elm 包管理器來安裝此包。

API

在此示例中,應用程式將與 Numbers API 通訊 – "http://numbersapi.com/#42"。

檢視

應用程式的檢視包含一個文字框和一個按鈕。

view : Model -> Html Msg
view model =
   div []
      [ h2 [] [text model.heading]
      ,input [onInput Input, value model.input] []
      , button [ onClick ShowFacts ] [ text "show facts" ]
      , br [] []
      , h3 [][text model.factText]
      ]

模型

模型表示使用者輸入的值以及 API 將返回的結果。

type alias Model =
   { heading : String
   , factText : String
   , input :String
   }

訊息

應用程式具有以下三個訊息:

  • ShowFacts
  • Input
  • NewFactArrived

單擊“顯示知識”按鈕時,ShowFacts 訊息將傳遞給更新方法。當用戶在文字框中鍵入某些值時,Input 訊息將傳遞給更新方法。最後,當接收到 Http 伺服器響應時,NewFactArrived 訊息將傳遞給更新。

type Msg
   = ShowFacts
   |Input String
   | NewFactArrived (Result Http.Error String)

更新

更新方法返回一個元組,其中包含模型和命令物件。當用戶單擊“顯示知識”按鈕時,訊息將傳遞給更新,然後更新呼叫 NumbersAPI。

update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
   case msg of
      Input newInput ->
      (Model "NumbersApi typing.." "" newInput ,Cmd.none)
      ShowFacts ->
         (model, getRadmonNumberFromAPI model.input)

      NewFactArrived (Ok newFact) ->
         (Model "DataArrived" newFact "", Cmd.none)

      NewFactArrived (Err _) ->
      (model, Cmd.none)

輔助函式

輔助函式 getRandomNumberFromAPI 呼叫 NumbersAPI 並將使用者輸入的數字傳遞給它。API 返回的結果用於更新模型。

getRadmonNumberFromAPI : String->Cmd Msg
getRadmonNumberFromAPI newNo =
   let
      url =
         "http://numbersapi.com/"++newNo
   in
      Http.send NewFactArrived (Http.getString url)
序號 方法 簽名 描述
1 Http.getString getString : String -> Request String 建立一個 GET 請求並將響應主體解釋為字串。
2 Http.send send:(Result Error a -> msg) -> Request a -> Cmd msg 傳送一個 Http 請求。

main

這是 Elm 專案的入口點。

main =
   Html.program
      { init = init
      , view = view
      , update = update
      , subscriptions = subscriptions
      }

綜合起來

步驟 1 - 建立資料夾 CommandApp 和檔案 CommandDemo.elm。

步驟 2 - 使用命令 elm package install elm-lang/http 安裝 http 模組。

步驟 2 - 鍵入 CommandDemo.elm 的內容,如下所示:

import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import Http

main =
   Html.program
      { init = init
      , view = view
      , update = update
      , subscriptions = subscriptions
      }

-- MODEL
type alias Model =
   { heading : String
   , factText : String
   , input :String
   }

init : (Model, Cmd Msg)
init =
   ( Model "NumbersAPI" "NoFacts" "42"-- set model two fields
   , Cmd.none -- not to invoke api initially
   )

-- UPDATE

type Msg
   = ShowFacts
   |Input String
   | NewFactArrived (Result Http.Error String)

update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
   case msg of
      Input newInput ->
      (Model "NumbersApi typing.." "" newInput ,Cmd.none)
      ShowFacts ->
         (model, getRadmonNumberFromAPI model.input)

      NewFactArrived (Ok newFact) ->
         (Model "DataArrived" newFact "", Cmd.none)

      NewFactArrived (Err _) ->
         (model, Cmd.none)

- VIEW

view : Model -> Html Msg
view model =
   div []
      [ h2 [] [text model.heading]
      ,input [onInput Input, value model.input] []
      , button [ onClick ShowFacts ] [ text "show facts" ]
      , br [] []
      , h3 [][text model.factText]
      ]

-- SUBSCRIPTIONS

subscriptions : Model -> Sub Msg
subscriptions model =
   Sub.none

-- HTTP

getRadmonNumberFromAPI : String->Cmd Msg
getRadmonNumberFromAPI newNo =
   let
      url =
      "http://numbersapi.com/"++newNo
   in
      Http.send NewFactArrived (Http.getString url)

步驟 4 - 執行命令。

C:\Users\dell\elm\CommandApp> elm make .\CommandDemo.elm

這將生成如下所示的 html 檔案。

Generate html
廣告