Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

ШРИ - JavaScript Event Model

Mikhail Davydov
September 23, 2013

ШРИ - JavaScript Event Model

Событийная модель. Базовые паттерны: PubSub, EventEmitter и EventManager. Дополнительные возможности для упрощения работы с событиями: namespace, событие с накоплением. Управление потоком событий и их фильтрация: trottle, debounce. События на DOM и Делегирование событий. Применение событийной модели для событийного ввода-вывода и организации скелета event-driven приложения.

Video https://events.yandex.ru/lib/talks/567/

Mikhail Davydov

September 23, 2013
Tweet

More Decks by Mikhail Davydov

Other Decks in Education

Transcript

  1. 4 PubSub •  Издатель (Publisher) –  Генерирует данные одного типа

    –  Издает только одну газету –  Издателей может быть много •  Подписчики (Subscribers) –  Подписываются на данные издателя –  Могут отписаться в любой момент •  Данные – поток –  Поздно подписался – упустил данные –  Объем и частота публикаций задается издателем
  2. 5 var PubSub = function () { this.readers = [];

    }; PubSub.prototype = { pub: function (data) {}, sub: function (callback) {}, unsub: function (callback) {} }; // function callback(data) {} PubSub – пример
  3. 6 PubSub – особенности •  Самая простая реализация •  Только

    1 тип данных –  А хочется еще и "Мурзилку" получать •  Нужно напрямую общаться с объектом
  4. 8 Event Emitter •  Имеет много названий •  Издатель – 

    Генерирует данные разных типов –  Издает газеты и журналы –  Издателей может быть много •  Подписчики –  Подписываются на данные любого типа в любом количестве –  Могут отписаться в любой момент •  Данные – поток –  Поздно подписался – упустил данные –  Объем и частота публикаций задается издателем
  5. 9 var EventEmitter = function () { // events =

    {"event_name": []}; this.events = {}; }; EventEmitter.prototype = { emit: function (event, data) {}, on: function (event, callback) {}, off: function (event, callback) {} }; // function callback(data) {} Event Emitter – пример
  6. 12 Event Manager •  Имеет много названий •  Своеобразная шина

    данных •  Единственный издатель –  Генерирует данные разных типов •  Подписчики –  Подписываются на данные любого типа в любом количестве –  Могут отписаться в любой момент •  Данные – поток –  Поздно подписался – упустил данные –  Объем и частота публикаций задается издателем
  7. 13 Похож на Event Emitter, но это Синглентон var EventManager

    = { events: {}, emit: function (event, data) {}, on: function (event, callback) {}, off: function (event, callback) {} }; // function callback(data) {} Event Manager – пример
  8. 18 Управление событиями •  Группировка событий –  namespace •  Легкое

    удаление событий –  Удаление события без callback –  Удаление по дескриптору
  9. 19 jQuery 1.8 var handler = function () {}; $('body').on('click.ns',

    handler); $('body').off('click', handler); // не удобно $('body').off('click'); // все click $('body').off('.ns'); // весь namespace $('body').off(); // все события $('body').off('**'); // все делегированные Управление событиями – пример
  10. 20 Накопление данных •  Опоздал с подпиской – ничего не

    получил –  Это не удобно •  Пользователь желает получить все –  Всю подписку журналов с нуля •  Как только подписался – сразу получил •  Похоже на Promise
  11. 21 jQuery DOMReady $(function () { $(function () { console.log('Tada!');

    }); }); Накопление данных – пример
  12. 22 jQuery Ajax#done var data = $.get('/'); data.done(function () {

    data.done(function () { console.log('Tada!'); }); }); Накопление данных – пример
  13. 24 Event bubbling •  Событие начинается с текущего элемента • 

    Поднимается по DOM дереву •  Последний элемент – корень дерева –  window или document
  14. 29 Event bubbling – фаза по умолчанию в jQuery //

    jQuery 1.7 .on() $('.b-form-button').on('click', function (event) { console.log(this); // .b-form-button element }); // Хэлперы $('.b-form-button').click(function (event) { console.log(event); }); Event bubbling в jQuery http://api.jquery.com/on/ http://api.jquery.com/category/events/ http://api.jquery.com/category/events/event-object/
  15. 30 Функция bindTo() BEM.DOM.decl('b-form-input', { onSetMod : { 'js' :

    { 'inited' : function () { this .bindTo(this.elem('input'), { 'focus' : this.onFocus, 'blur' : this.onBlur }); } } } }); Event bubbling в i-bem http://bem.github.com/bem-bl/sets/common- desktop/i-bem/i-bem.ru.html
  16. 31 Не всплывающие события •  var itBubbles = event.bubbles;! • 

    Специфичные события для 1 элемента –  submit, focus, blur, load, unload, change, reset, scroll •  Некоторые события мутаций DOM –  DOMFocusIn, DOMFocusOut, DOMNodeRemoved https://developer.mozilla.org/en-US/docs/ Mozilla_event_reference
  17. 32 Особенности •  Фазы Capturing & Bubbling идут одновременно – 

    Чередуются capturing, bubbling •  Каждый обработчик получает новый инстанс объекта Event http://jsfiddle.net/h2nJU/2/
  18. 42 Профит делегирования •  Меньше обработчиков событий –  Экономия памяти

    –  Меньше утечек памяти •  Проще работать с динамическими элементами
  19. 43 Особенности делегирования •  Если событие не всплывает – ничего

    не получится •  Нужно максимально ограничивать событие –  Необходимо выбрать наиболее близкого делегата •  Возможны частые ложные вызовы события –  Большие затраты на вызов функции •  Ограничить делегирование у частых событий –  mousemove •  Не использовать делегирование если элемент 1
  20. 44 // jQuery 1.7+ .on() $('.b-container') .on('click', '.b-item', function (event)

    { console.log(this); // .b-item }); // jQuery 1.3+ $('.b-item') .live('click', function (event) { console.log(this); // .b-item }); // === $(document).on('click', '.b-item') Делегирование в jQuery http://api.jquery.com/on/ http://api.jquery.com/live/
  21. 46 Прерывание всплытия •  event.stopPropagation() –  Прерывает всплытие события по

    дереву •  event.stopImmediatePropagation() –  Прерывает всплытие события по дереву –  Отменяет прочие обработчики http://www.w3.org/TR/DOM-Level-2-Events/ events.html#Events-Event-stopPropagation
  22. 47

  23. 48 Прерывание действия по умолчанию •  Действие по умолчанию – 

    Переход по ссылке –  Раскрытие <select> –  Сабмит формы –  Фокус в инпут –  Снятие фокуса •  event.preventDefault() –  Перерывает это действие •  Некоторые действия прервать нельзя –  var isCanPrevent = event.cancelable; –  resize, scroll, focus, error, load, unload, DOM*, … https://developer.mozilla.org/en-US/docs/DOM/ event.preventDefault
  24. 49 $('.b-link').click('click', function (event) { return false; // preventDefault+stopPropagation });

    $('.b-form').click('submit', function (event) { return isValid(this); // this - .b-form }); $('.b-link').click('click', function (event) { event.preventDefault(); event.stopPropagation(); }); Прерывание событий jQuery http://api.jquery.com/on/ http://api.jquery.com/live/
  25. 55 var log = $.throttle(250, function () { console.log(arguments); });

    $(window).scroll(log); $(window).off('scroll', log); $.throttle http://benalman.com/code/projects/jquery-throttle- debounce/examples/throttle/
  26. 62 Вариант не удачного использования событий DataObject.on('someData', function (data) {

    console.log(data); }); DataObject.trigger('giveMe:someData'); Событие геттер
  27. 71 Накладные расходы •  Событие – функция –  n объектов,

    k ресурсов = n*k функций –  функция занимает ресурсы –  лишние скоупы, сборка мусора и JIT-компиляция –  вызов кучи функций –  утечки памяти
  28. 73 Не блокирующий I/O •  Дефрагментация времени блокировок –  Более

    плотная загрузка процесса •  Выгодно применять, когда время I/O больше времени обработки данных •  Меньше проблем с разделяемой памятью
  29. 74 Слабое связывание •  Элементы не знают о программе • 

    Элементы общаются только событиями •  Меньше разделенной памяти –  Меньше проблем синхронизации
  30. 76 Заключение •  События –  PubSub –  Event Emitter – 

    Event Manager •  Фичи событий –  namespace –  накопление данных •  DOM события –  Event Bubbling –  Делегирование –  Прерывание события –  Отмена действия по умолчанию •  Фильтрация