【问题标题】:Using elm higher order functions for keyboard events使用 elm 高阶函数处理键盘事件
【发布时间】:2016-09-27 12:27:17
【问题描述】:

我正在尝试创建一个高阶函数来创建仅捕获特定键代码的函数。该代码的灵感来自 Evan 的 onEnter 函数,该函数来自他的 todomvc 实现,该实现仅捕获 enter 函数。

onKeyCode : Int -> Msg -> Attribute Msg
onKeyCode keycode msg =
    let
        captureKey code =
            if code == keycode then
                msg
            else
                NoOp
    in
        on "keydown" (Json.map captureKey keyCode)

onEnter = onKeyCode 13
onEsc =  onKeyCode 27

现在我想将它添加到查看器中的输入组件中:

input
 [ class "edit"
 , id ("todo-" ++ toString item.uid)
 , value item.message
 , onInput (UpdateItem item.uid)
 , onBlur (SwitchEditTodo item.uid False)
 , onEnter (SwitchEditTodo item.uid False)
 , onEsc (UndoEditTodo item.uid)
 ]
[]

如果我只有onEnter,代码将按预期工作,但如果我添加onEsconEnter 代码将永远不会执行。我在哪里做错了?这是高阶函数上下文或在单独函数中具有多个值的“on”映射的问题吗?

【问题讨论】:

    标签: functional-programming dom-events elm


    【解决方案1】:

    您正在向输入元素添加两个onkeydown 属性,并且只有其中一个可以获胜。列表中的第二个覆盖第一个。如果在幕后使用addEventListener,情况就不是这样了,但现在我们可以用稍微不同的方法来解决它。

    您可以编写一个onKeysDown 函数,该函数接受可能的键代码列表以及它们应该调用的消息,如下所示:

    onKeysDown : List (Int, Msg) -> Attribute Msg
    onKeysDown keys =
      let
        captureKey code =
          List.filterMap (\(k, m) -> if k == code then Just m else Nothing) keys
            |> List.head
            |> Maybe.withDefault NoOp
      in
        on "keydown" (Json.map captureKey keyCode)
    

    然后您可以编写用于处理特定键的速记函数,如下所示:

    enter msg = (13, msg)
    esc msg = (27, msg)
    

    现在您可以像这样在视图中使用它:

    input
        [ ...
        , onKeysDown
          [ enter <| SwitchEditTodo item.uid False
          , esc <| UndoEditTodo item.uid
          ]
        ]
    

    之所以有效,是因为它会生成一个 keydown 事件处理程序属性。当你用一个预定义的元组替换一个高阶函数时,它仍然给你同样可读的代码。

    【讨论】:

    • 从您的评论中,我了解到这种覆盖效果是 html/JavaScript 产生的副作用,因为即使我创建了几个“on”事件,我毕竟只是在封面让我可以覆盖自己。
    • 正确,这是多个同名 html 属性的限制,而不是 Elm 的限制(尽管有一些警告会很好)。如果你尝试在原始 html 中做同样的事情,你会看到同样的问题
    猜你喜欢
    • 1970-01-01
    • 2021-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-14
    • 1970-01-01
    相关资源
    最近更新 更多