使用Elm高阶函数进行键盘事件

维克多·R·埃斯科巴尔

我试图创建一个高阶函数来创建仅捕获特定键代码的函数。该代码的灵感来自于Evan的todomvc实现中的“ onEnter”函数,该实现仅捕获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,则代码将按预期工作,但如果添加onEsc,则永远不会执行onEnter代码。我在哪里做错了?是否存在高阶函数上下文或在单独函数中具有多个值的“ on”映射问题?

乍得·吉尔伯特

您正在向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事件处理程序属性。并且,尽管您将预定义的元组替换为高阶函数,但它仍然为您提供可读的代码。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章