【问题标题】:How to "generate" own commands in simple application如何在简单的应用程序中“生成”自己的命令
【发布时间】:2017-05-25 08:18:58
【问题描述】:

作为 elm 的学习示例,我想用 elm 架构创建一个简单的蛇游戏。

这里是到目前为止的完整代码: https://gist.github.com/DanEEStar/b11509514d72eaafb640378fc7c93b44

程序的一部分是由单击按钮生成的UpdateWorld 消息和在用户按下空格键时调用的updateWorld 函数。

这导致以下编译和工作代码(sn-ps 形成完整代码):

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        UpdateWorld ->
            ( updateWorld model, Cmd.none )

        KeyPress keyCode ->
            ( handleInput keyCode model, Cmd.none )


handleInput : Int -> Model -> Model
handleInput keyCode model =
    case Char.fromCode keyCode of
        ' ' ->
            updateWorld model

        _ ->
            model


updateWorld : Model -> Model
updateWorld model =
    { model | snake = updateSnake model.snake }


subscriptions : Model -> Sub Msg
subscriptions model =
    Keyboard.presses KeyPress


view : Model -> Html Msg
view model =
    div []
        -- here I can simply tell `onClick` to generate the `UpdateWorld` command
        [ button [ onClick UpdateWorld ] [ text "tick" ]
        ]

在这段代码 sn-ps 中,很明显onClick 事件生成了UpdateWorld 命令。 但在handleInput 函数中,我必须“手动”调用updateWorld 函数。

我宁愿从我的handleInput 函数“生成”一个新的UpdateWorld 命令。我认为这将澄清代码。比如:

handleInput keyCode =
    case Char.fromCode keyCode of
        ' ' ->
            -- how can I generate this command in my code
            UpdateWorld

我该怎么做?

这是一个好主意,还是更好的模式?

【问题讨论】:

    标签: elm


    【解决方案1】:

    回想一下,update 只是一个函数,这意味着您可以递归调用它。

    考虑将handleInput 的签名更改为也返回(Model, Cmd Msg),就像update 函数一样:

    handleInput : Int -> Model -> (Model, Cmd Msg)
    handleInput keyCode model =
        case Char.fromCode keyCode of
            ' ' ->
                update UpdateWorld model
            'a' ->
                { model | snake = changeSnakeDirection model.snake West } ! []
            ...
    

    您可以去掉 updateWorld 函数并将该代码移动到 UpdateWorld 消息处理程序:

    update : Msg -> Model -> ( Model, Cmd Msg )
    update msg model =
        case msg of
            UpdateWorld ->
                ( { model | snake = updateSnake model.snake }, Cmd.none )
    
            ChangeDirection newDirection ->
                ( { model | snake = changeSnakeDirection model.snake newDirection }, Cmd.none )
    
            KeyPress keyCode ->
                handleInput keyCode model
    

    【讨论】:

    • 谢谢,这正好解决了我的问题。我看错了角落。
    • 我必须拿走接受标志。在对这个问题进行了更多思考之后,我仍然对原来的问题感兴趣......
    • 我偶然发现了你的这个答案:stackoverflow.com/a/42703561/669561。这似乎和我有同样的问题?!​​
    • 是的,正如该答案中所解释的那样,虽然可以为特定的 Msg 触发另一个 Cmd,但您可以/应该坚持只递归调用 update,除非您有想要经历另一个 Elm 架构事件周期的明确原因。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-29
    • 2012-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-21
    相关资源
    最近更新 更多