Víc*_*bar 8 functional-programming javascript-events elm
我正在尝试创建一个更高阶的函数来创建函数来捕获特定的密钥代码.该代码的灵感来自于他的todomvc实现中的Evan的"onEnter"功能,该功能仅捕获输入功能.
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
Run Code Online (Sandbox Code Playgroud)
现在我想将它添加到查看器中的输入组件:
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)
]
[]
Run Code Online (Sandbox Code Playgroud)
如果我只有onEnter,代码将按预期工作,但如果我添加onEsc,onEnter代码永远不会执行.我在哪里做错了?是高阶函数上下文的问题还是在单独的函数中使用多个值进行"on"映射?
您正在向onkeydowninput元素添加两个属性,并且只有其中一个可以获胜.列表中的第二个将覆盖第一个.如果它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)
Run Code Online (Sandbox Code Playgroud)
然后,您可以编写速记函数来处理特定的键,如下所示:
enter msg = (13, msg)
esc msg = (27, msg)
Run Code Online (Sandbox Code Playgroud)
现在你可以在你的视图中使用它,如下所示:
input
[ ...
, onKeysDown
[ enter <| SwitchEditTodo item.uid False
, esc <| UndoEditTodo item.uid
]
]
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为它生成单个keydown事件处理程序属性.虽然您将预定义的元组替换为更高阶函数,但它仍然为您提供可读代码.