2015-02-05 60 views
2

我刚开始使用Bacon.js,它确实很棒。虽然有时候我很难找到正确的做事方式。例如,我想要一个带有可拖动部分的角度指令。我无耻地选择了某人的jsBin,并试图修改该代码的角度FRP,角度和全局事件处理程序

我想制作一个可调整大小的列表。所以,如果我做这样的事情 在列头指令

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" 

这有点儿工作,但现在这个指令将注册“鼠标移动”和遍布页“鼠标松开”事件。我可能会添加一些takeWhile声明,事实上我只是尝试过,并没有真正奏效。

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

  • 您可以创建一个指令处理程序,然后使用takeWhile, takeUntil但随后,将工作只有一次,由于上述流最终停止。每次需要回复document.click时,是否必须重新初始化流? 在一堆地方有“文档”级别的事件也不是件坏事吗?如果你编写指令$(document).asEventStream('mouseup')并使用该指令两百次,是不是会创建实际的200个监听器?

  • 或者你必须在全球范围引进这些类型的流变量对整个应用程序使用,然后指令里面做mapfilterreduce?但是,如果有人拨打takeUntil和流停止完全流动,不能用于应用程序的其他部分?

  • 或者也许听应用程序的顶层并发出$ rootScope事件的每个值在流中,然后在指令或视图中使用ng-bacon's$rootScope.$asEventStream(event)? 难道这不会使应用程序的响应速度变慢吗?假如你需要回答'keydown'和'keyup'事件?

有人能告诉我一个例子,如何FRP在角指令一起使用(特别是拖-N-下降样本,将不胜感激)

回答

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

+0

所以这里使用'takeWhile'和'takeUntil'问题。让我描述一下。比方说,我有一个指令,当它悬停时打开一个div,然后当用户点击任何地方(document.click)它关闭div。这两个操作都由'toEventStream'流管理。我可以在后面使用'takeUntil',但它会完全停止流,我如何重新注册流?当我尝试从其他的'onValue'中绑定一个'toEventStream'时,它不起作用。 – Agzam 2015-02-06 20:48:20

+0

我还读过培根无论如何都使用单身的地方。所以在一堆地方注册文档级别的事件是很好的。仍然需要明智地使用它们(使用'takeWhile'和'takeUntil') – Agzam 2015-02-06 20:51:06

+0

取消注册的一个好方法是保持“关闭”流。当模块/指令/代码的任何部分被关闭/被销毁时,该流获得一个值。您将'takeUntil(close)'添加到您使用的所有流中,在这种情况下,它足以将其添加到开始。 – OlliM 2015-02-07 19:00:14