FRP、角度和全局事件处理程序

FRP, angular and global event handlers

本文关键字:全局 事件处理 程序 FRP      更新时间:2023-09-26

我刚开始使用Bacon.js,它真的很棒。尽管有时我确实很难找到正确的做事方式。例如,我想要一个带有可拖动零件的角度指令。我无耻地挑选了某人的jsBin,并试图将该代码改编为角度

我正在尝试制作一个具有可调整大小的列的表。所以如果我这样做列标题指令

link: (scope, element, attrs)->
    el = element.find('.column-separator')
    doc = $(document)
    mMove = doc.asEventStream('mousemove')
    startDrag = el.asEventStream('mousedown')
    endDrag = doc.asEventStream('mouseup').takeWhile mMove
    # in this case unlike the example in jsBin I don't care about vertical axis, 
    # only horizontal "X"
    getDelta = (t)-> a = t[1]; b = t[0]; return a-b   
    add = (p1,p2)-> p1 + p2
    draggingDeltas = startDrag.flatMap ->
        return mMove
                .map '.clientX'
                .slidingWindow 2,2
                .map getDelta
                .takeUntil endDrag
    pos = draggingDeltas.scan 0, add
    pos.onValue (pos)-> el.css left: pos+"px"

这有点奏效,但现在这个指令会在整个页面上注册"mousemove"answers"mouseup"事件。我可能可以添加一些takeWhile语句,事实上,我只是尝试了一下,但并没有真正起作用。

我的意思是,在angular应用程序中使用像$(document).asEventStream('click')这样的全局事件处理程序的模式是什么

  • 您可以在指令中创建处理程序,然后使用takeWhile, takeUntil,但这只能工作一次,因为流最终会停止。是否每次需要响应document.click时都必须重新初始化流?此外,在一堆地方举办"文档"级别的活动不是一件坏事吗?如果你在一个指令$(document).asEventStream('mouseup')中编写并使用该指令200次,这难道不会创建实际的200个侦听器吗?

  • 或者,您必须全局引入这类流变量供整个应用程序使用,然后在指令中执行mapfilterreduce?但是,如果有人调用takeUntil,流完全停止流动,无法在应用程序的其他部分使用,该怎么办?

  • 或者,可以在应用程序的顶层侦听,并为流中的每个值发出$rootScope事件,然后在指令或视图中使用ng培根的$rootScope.$asEventStream(event)?这难道不会降低应用程序的响应速度吗?说你是否需要对"keydown"answers"keyup"事件做出回应?

有人能给我看一个FRP如何在角度指令中使用的例子吗?(特别是drag-N-drop样品)

我不确定这是否符合角度哲学,但我肯定只添加一次这些处理程序。

在全局单例类中:

var mouseHandler = {
  up: $(document).asEventStream('mouseup'),
  move: $(document).asEventStream('mousemove')  
} 

在单个组件中,您可以向这些事件添加处理程序,但要确保始终使用takeUntil,这样培根只有在实际需要时才能处理这些事件。

function dragHandler(element) {
  var start = $(element).asEventStream('mousedown')
  var delta = start.flatMap(function() {
    return mouseHandler.move
      .map('.clientX')
      .slidingWindow(2,2)
      .map(getDelta)
      .takeUntil(mouseHandler.up)
  })
  var pos = delta.scan(0, add)
  pos.onValue(function(p) {
    $(element).css({left: p + "px"})
  })
  function getDelta(t) { return t[1]-t[0] }
  function add(a,b) { return a+b }
}

http://jsbin.com/yekojitake/3/edit