[英]Halogen keyboard-input example and unsubsribing to the events?
如何从键盘输入示例中的 HandleKey 以外的其他操作取消订阅键盘事件? (问题与 Halogen 2.0.1 版和 purescript 0.11.4 版有关。)
在示例中,输入/返回有效。 我有一组可以通过按下关闭按钮用鼠标折叠的元素,关闭操作会处理它。 此外,输入/返回可用于折叠元素,它可以正常工作。
Open next -> do
st <- H.get
if not st.open
then do
H.modify (_ { open = true })
eval (H.action Init)
else pure unit
pure next
Close next -> do
H.modify (_ { open = false })
st <- H.get
case st.unsubscribe of
Nothing -> pure unit
-- Just smth -> H.liftAff smth
Just _ -> H.modify (_ { unsubscribe = Nothing}) -- H.liftAff us
pure next
Init next -> do
H.modify (_ { open = true})
document <- H.liftEff $ DOM.window >>= DOM.document <#> DOM.htmlDocumentToDocument
H.subscribe $ ES.eventSource'
(K.onKeyUp document)
(Just <<< H.request <<< HandleKey)
-- H.modify (_ { unsubscribe = ??? })
pure next
问题是,当我用鼠标关闭(折叠)元素时,事件侦听器不会被删除(未完成)并且它仍然存在。 当我重新打开元素时,上面的代码将建立第二个(第三个、第四个等)侦听器,然后每个按键都会被多次处理。
我正在考虑创建一个键盘事件,但在这里听起来不是正确的方法。
所以问题是:
进一步的问题:
unsubscribe
。 如何使用它?后期编辑:这似乎与有关动态附加事件侦听器的问题有关,另请参阅this 、 this和this 。
其中一个答案说,只有通过使用状态才能了解动态处理程序,这解决了我的问题。 无论如何,我认为这里提到的问题仍然存在(如何使用 Halogen 删除处理程序,尤其是关于示例中的取消订阅字段 - 它以某种方式可用吗?)
我花了一段时间才理解 eventSource 的签名,但这里有一个细分,可能有助于澄清发生了什么。
这才是真正的签名...
eventSource' :: forall f m a eff. MonadAff (avar :: AVAR | eff) m =>
((a -> Eff (avar :: AVAR | eff) Unit) -> Eff (avar :: AVAR | eff) (Eff (avar :: AVAR | eff) Unit)) ->
(a -> Maybe (f SubscribeStatus)) ->
EventSource f m
如果我们使用某种伪代码来命名签名的组件......
type Callback a = (a -> Eff (avar :: AVAR | eff) Unit)
type MaybeQuery a = (a -> Maybe (f SubscribeStatus))
type RemoveEventListener = (Eff (avar :: AVAR | eff) Unit)
我们得到...
eventSource' :: forall f m a eff.
(Callback a -> Eff (avar :: AVAR | eff) RemoveEventListener) ->
MaybeQuery a ->
EventSource f m
我认为您缺少的部分是 RemoveEventListener 部分。 下面是 HTMLDocument 上 onMouseUp 的示例 EventSource,它不像您引用的示例那样使用外部函数接口 (FFI)。
import DOM.Event.Types as DET
import DOM.Event.EventTarget as DEET
import DOM.HTML.Event.EventTypes as EventTypes
onMouseUp :: forall e
. DHT.HTMLDocument
-> (DET.Event -> Eff (CompEffects e) Unit)
-> Eff (CompEffects e) (Eff (CompEffects e) Unit)
onMouseUp doc callback = do
let eventTarget = (DHT.htmlDocumentToEventTarget doc)
-- Create an EventListener that will log a message
-- and pass the event to the callback
let listener =
DEET.eventListener (\event -> do
log "mouseUp"
callback event
)
-- Add the EventListener to the
-- document so it will fire on mouseup
DEET.addEventListener
EventTypes.mouseup
listener true eventTarget
-- Return the function that will later
-- remove the event listener
pure $ DEET.removeEventListener
EventTypes.mouseup
listener true eventTarget
所以回调将获得a
事件(在这种情况下是一个通用的Event
)。 请注意,我们必须创建对侦听器的引用,因此我们可以将相同的引用传递给 addEventListener 作为 removeEventListener(函数引用的作用就像一个 id 来确定删除哪个侦听器函数)。
MaybeQuery 函数也将传递a
事件,因此 Halogen 可以执行查询,您可以决定是否应该继续侦听事件。 该查询将需要像这样结构......
data YourQuery =
| HandleEvent Event (SubscribeStatus -> a)
eval (HandleEvent event reply) =
-- Decided if you want to keep listening
-- or now.
-- Keep listening...
-- pure $ reply (H.Listening)
-- Stop listening. Halogen will call the removeEventListener
-- function you returned from onMouseUp earlier
-- pure $ reply (H.Done)
并展示如何订阅 EventSource ...
import DOM.HTML.Window as Win
import Halogen.Query.EventSource as HES
document <- H.liftEff $ (window >>= Win.document)
H.subscribe $ HES.eventSource'
(onMouseUp document)
(Just <<< H.request <<< HandleEvent)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.