我刚刚开始使用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个侦听器吗?
或者您必须全局介绍这些流变量以供整个应用使用,然后在指令中执行map
,filter
和reduce
?但是,如果有人调用takeUntil
并且流停止完全流动并且无法在应用的其他部分使用,该怎么办?
或者听一下应用程序的顶层并为流中的每个值发出$ rootScope事件,然后在指令或视图中使用ng-bacon's $rootScope.$asEventStream(event)
?
这不会使应用程序的响应性降低吗?如果您需要回复“keydown”和“keyup”活动,请说明什么?
有人能告诉我一个例子,如何在角度指令中使用FRP(尤其是拖拽N-drop样本)
答案 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 }
}