Elm - 命令
在前面的章节中,我们讨论了 Elm 架构的各个组件及其功能。用户和应用程序使用消息相互通信。
考虑一个示例,其中应用程序需要与其他组件(例如外部服务器、API、微服务等)通信以服务于用户请求。这可以通过在 Elm 中使用命令来实现。消息和命令不是同义词。消息表示最终用户和应用程序之间的通信,而命令表示 Elm 应用程序如何与其他实体通信。命令是响应消息触发的。
下图显示了一个复杂的 Elm 应用程序的工作流程:
用户与视图交互。视图根据用户的操作生成相应的消息。更新组件接收此消息并触发一个命令。
语法
定义命令的语法如下所示:
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 文件。