2015-02-05 3 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" 

Это своего рода работает, но теперь эта директива будет регистрировать «MouseMove» и «» MouseUp события по всей странице. Я, вероятно, могу добавить некоторые заявления , и дело в том, что я просто попытался, и на самом деле это не сработало.

Я имею в виду, что такое шаблон использования глобального обработчика событий, как $(document).asEventStream('click') в угловом приложении?

  • Вы можете создать обработчик в директиве, а затем использовать takeWhile, takeUntil, но тогда это будет работать только один раз, так как поток в конце концов останавливается. Вам нужно повторно инициализировать поток каждый раз, когда вам нужно ответить на document.click? Не так ли плохо, что события уровня «документа» в кучке мест? Если вы пишете в директиве $(document).asEventStream('mouseup') и используете эту директиву двести раз, не создадут ли фактические двести слушателей?

  • Или вам нужно ввести эти рода потоковые переменные глобально для всего приложения для использования, а затем внутри директивы сделать map, filter и reduce? Но тогда, если кто-то называет takeUntil, и поток полностью прекращается и не может использоваться в других частях приложения?

  • Или, может быть, прослушать на верхнем уровне приложения и испустить событие $ rootScope для каждого значения в потоке, а затем в директиве или представлении использовать $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' для более позднего, но затем полностью останавливает поток, как мне перерегистрировать поток? Когда я пытался связать один «toEventStream» изнутри 'onValue' другого, это не сработало. – Agzam

+0

также я где-то читал, что Бэкон все равно использует одинарные. Таким образом, регистрация событий уровня документа в кучке мест прекрасна. Все еще нужно использовать их с умом (с 'takeWhile' и' takeUntil') – Agzam

+0

Один хороший способ отменить регистрацию - сохранить «близкий» поток. Этот поток получает значение, когда модуль/директива/любая часть кода закрывается/уничтожается. Вы добавляете 'takeUntil (close)' ко всем потокам, которые вы используете, в этом случае достаточно добавить его для запуска. – OlliM