javascript - FRP、 Angular 和全局事件处理程序

标签 javascript angularjs frp rxjs bacon.js

我刚刚开始使用Bacon.js这真的很棒。尽管有时我确实很难找到正确的做事方式。例如,我想要一个带有可拖动部分的 Angular Directive(指令)。我无耻地挑别人的jsBin并尝试调整该代码以适应 Angular

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

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 语句,事实上我只是尝试过,但它并没有真正起作用。

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

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

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

  • 或者可能在应用程序的顶层监听并为流中的每个值发出 $rootScope 事件,然后在指令或 View 中使用 ng-bacon's $rootScope.$asEventStream(event)? 这不会降低应用程序的响应速度吗?说说您是否需要响应“keydown”和“keyup”事件?

有人可以向我展示一个如何在 Angular Directive(指令)中使用 FRP 的示例(特别是拖放示例,我们将不胜感激)

最佳答案

我不确定这到底如何符合 Angular 哲学,但我肯定只会添加这些处理程序一次。

在全局单例类中:

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

在单个组件内部,您可以向其中添加处理程序,但请确保始终使用 takeUntil,这样 bacon 仅在实际需要时才处理这些事件。

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

关于javascript - FRP、 Angular 和全局事件处理程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28355472/

相关文章:

c# - XSockets - 自定义 Controller 未注册

javascript - jquery scroll 无法监听脚本文件中的事件

javascript - 如何通过 Angular js将json从指令传递到 Controller

c++ - 为什么 boost::signals2::signal<T>::connect 需要复制构造函数?

ios - 让过滤器和映射链接在 ReactiveCocoa 3.0 beta swift 上工作

javascript - jQuery选择的嵌套dom元素的后序遍历

javascript - 从源中完全删除标签

javascript - 在 AngularJs 中使用 Audio 标签渲染 Audio 元素

javascript - 在angularjs中的DHtmlX调度程序上添加时间线事件

haskell - 在重新启动内执行 MonadIO 操作