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

时间:2015-02-05 22:42:55

标签: javascript angularjs frp rxjs bacon.js

我刚刚开始使用Bacon.js,这真的很棒。虽然有时候我很难找到正确的做事方式。例如,我想要一个带有可拖动部分的角度指令。我无耻地挑选某人的jsBin,并试图使该代码适应角度

我正在尝试使用可调整大小的列创建一个表。所以,如果我做这样的事情 在column-header指令

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'和'mouseup'事件。我可能会添加一些takeWhile语句,而事实上我只是尝试了它并没有真正起作用。

我的意思是在角应用中使用全局事件处理程序(如$(document).asEventStream('click'))的模式是什么?

  • 您可以在指令中创建处理程序然后使用takeWhile, takeUntil,但之后只能使用一次,因为流最终会停止。每次需要回复document.click时,是否必须重新初始化流? 在一堆地方举办“文件”级别活动也不是一件坏事吗?如果您在指令$(document).asEventStream('mouseup')中写入并使用该指令200次,那么这不会创建实际的200个侦听器吗?

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

  • 或者听一下应用程序的顶层并为流中的每个值发出$ rootScope事件,然后在指令或视图中使用ng-bacon's $rootScope.$asEventStream(event)? 这不会使应用程序的响应性降低吗?如果您需要回复“keydown”和“keyup”活动,请说明什么?

有人能告诉我一个例子,如何在角度指令中使用FRP(尤其是拖拽N-drop样本)

1 个答案:

答案 0 :(得分:2)

我不确定这究竟是如何适应角度哲学的,但我肯定只会添加一次这些处理程序。

在全球单身人士课程中:

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