functional-programming - 将 elm 高阶函数用于键盘事件

标签 functional-programming dom-events elm

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

最佳答案

您正在添加两个 onkeydown input 元素的属性,并且只有其中一个可以获胜。列表中的第二个覆盖第一个。是否使用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)

现在你可以像这样在你的 View 中使用它:

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

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

关于functional-programming - 将 elm 高阶函数用于键盘事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39724695/

相关文章:

ELM 自定义元素

elm - 是否可以使用 elm-decode-pipeline 有条件地解码某些字段

haskell - 如何在 Haskell 中创建二维数组?

javascript - 为什么 onbeforeunload 事件没有触发

openapi - 如何在 Playground 更新函数中发出 http 请求?

javascript - 从浏览器的网络控制台获取信息

javascript - 如何删除在 TypeScript 中使用 "this"的事件监听器?

list - 删除语法糖 : List comprehension in Haskell

web-applications - 如何检测 Racket Web 应用程序上的按键?

.net - F# 中的宏支持