Михаил Давыдов — JavaScript: События

4,862 views

Published on

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Михаил Давыдов — JavaScript: События

  1. 1. JavaScriptСобытияМихаил ДавыдовРазработчик JavaScript
  2. 2. Паттерн PubSub
  3. 3. PubSub •  Издатель (Publisher) –  Генерирует данные одного типа –  Издает только одну газету –  Издателей может быть много •  Подписчики (Subscribers) –  Подписываются на данные издателя –  Могут отписаться в любой момент •  Данные – поток –  Поздно подписался – упустил данные –  Объем и частота публикаций задается издателем4
  4. 4. PubSub – пример var PubSub = function () { this.readers = []; }; PubSub.prototype = { pub: function (data) {}, sub: function (callback) {}, unsub: function (callback) {} }; // function callback(data) {}5
  5. 5. PubSub – особенности •  Самая простая реализация •  Только 1 тип данных –  А хочется еще и "Мурзилку" получать •  Нужно напрямую общаться с объектом6
  6. 6. Event Emitter
  7. 7. Event Emitter •  Имеет много названий •  Издатель –  Генерирует данные разных типов –  Издает газеты и журналы –  Издателей может быть много •  Подписчики –  Подписываются на данные любого типа в любом количестве –  Могут отписаться в любой момент •  Данные – поток –  Поздно подписался – упустил данные –  Объем и частота публикаций задается издателем8
  8. 8. Event Emitter – пример 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) {}9
  9. 9. Event Emitter – особенности •  Много разных типов данных •  Нужно иметь ссылку на EventEmitter10
  10. 10. Event Manager11
  11. 11. Event Manager •  Имеет много названий •  Своеобразная шина данных •  Единственный издатель –  Генерирует данные разных типов •  Подписчики –  Подписываются на данные любого типа в любом количестве –  Могут отписаться в любой момент •  Данные – поток –  Поздно подписался – упустил данные –  Объем и частота публикаций задается издателем12
  12. 12. Event Manager – пример Похож на Event Emitter, но это Синглентон var EventManager = { events: {}, emit: function (event, data) {}, on: function (event, callback) {}, off: function (event, callback) {} }; // function callback(data) {}13
  13. 13. Event Manager – особенности •  Много разных типов данных •  Об этом объекте знают все14
  14. 14. Дополнительные фичи Управление событиями, namespace Накопление данных События на дереве DOM Делегирование событий Фильтрация событий
  15. 15. Их наличие зависит отконкретны задач
  16. 16. Фичи направлены науправление группамисобытий и агрегацией
  17. 17. Управление событиями •  Группировка событий –  namespace •  Легкое удаление событий –  Удаление события без callback –  Удаление по дескриптору18
  18. 18. Управление событиями – пример 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(**); // все делегированные19
  19. 19. Накопление данных •  Опоздал с подпиской – ничего не получил –  Это не удобно •  Пользователь желает получить все –  Всю подписку журналов с нуля •  Как только подписался – сразу получил •  Похоже на Promise20
  20. 20. Накопление данных – пример jQuery DOMReady $(function () { $(function () { console.log(Tada!); }); });21
  21. 21. Накопление данных – пример jQuery Ajax#done var data = $.get(/); data.done(function () { data.done(function () { console.log(Tada!); }); });22
  22. 22. DOM событияСобытия на DOM деревеEvent bubblingEvent capturingНе всплывающие события
  23. 23. Event bubbling •  Событие начинается с текущего элемента •  Поднимается по DOM дереву •  Последний элемент – корень дерева –  window или document24
  24. 24. Event bubbling <div> <div> <div> *Click*25
  25. 25. Event bubbling <div> <div> <div> *Click*26
  26. 26. Event bubbling <div> <div> <div> *Click*27
  27. 27. Event bubbling <div> <div> <div> *Click*28
  28. 28. Event bubbling в jQuery 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); }); http://api.jquery.com/on/ http://api.jquery.com/category/events/ 29 http://api.jquery.com/category/events/event-object/
  29. 29. Event bubbling в i-bem Функция bindTo() BEM.DOM.decl(b-form-input, { onSetMod : { js : { inited : function () { this .bindTo(this.elem(input), { focus : this.onFocus, blur : this.onBlur }); } } } }); http://bem.github.com/bem-bl/sets/common-30 desktop/i-bem/i-bem.ru.html
  30. 30. Не всплывающие события •  var itBubbles = event.bubbles;! •  Специфичные события для 1 элемента –  submit, focus, blur, load, unload, change, reset, scroll •  Некоторые события мутаций DOM –  DOMFocusIn, DOMFocusOut, DOMNodeRemoved https://developer.mozilla.org/en-US/docs/31 Mozilla_event_reference
  31. 31. Особенности •  Фазы Capturing & Bubbling идут одновременно –  Чередуются capturing, bubbling •  Каждый обработчик получает новый инстанс объекта Event32 http://jsfiddle.net/h2nJU/2/
  32. 32. ДелегированиеОдин обработчик – несколько целейОснова – всплытие событий
  33. 33. Делегирование <ul> onclick=delegateClick <li class="good"> *Click* <li class="good"> <li class="bad">34
  34. 34. Делегирование – начало события <ul> onclick=delegateClick <li class="good"> *Click* <li class="good"> <li class="bad">35
  35. 35. Делегирование – всплытие события <ul> onclick=delegateClick <li class="good"> *Click* <li class="good"> <li class="bad">36
  36. 36. var isTarget = event.target.classList .contains(good);37
  37. 37. Делегирование <ul> onclick=delegateClick <li class="good"> <li class="good"> <li class="bad"> *Click*38
  38. 38. Делегирование – начало события <ul> onclick=delegateClick <li class="good"> <li class="good"> <li class="bad"> *Click*39
  39. 39. Делегирование – всплытие события <ul> onclick=delegateClick <li class="good"> <li class="good"> <li class="bad"> *Click*40
  40. 40. Событие не произойдет contains(good) === false;41
  41. 41. Профит делегирования •  Меньше обработчиков событий –  Экономия памяти –  Меньше утечек памяти •  Проще работать с динамическими элементами42
  42. 42. Особенности делегирования •  Если событие не всплывает – ничего не получится •  Нужно максимально ограничивать событие –  Необходимо выбрать наиболее близкого делегата •  Возможны частые ложные вызовы события –  Большие затраты на вызов функции •  Ограничить делегирование у частых событий –  mousemove •  Не использовать делегирование если элемент 143
  43. 43. Делегирование в jQuery // 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) http://api.jquery.com/on/ 44 http://api.jquery.com/live/
  44. 44. Управление DOM событием Прерывание всплытия Прерывание действия по умолчанию
  45. 45. Прерывание всплытия •  event.stopPropagation() –  Прерывает всплытие события по дереву •  event.stopImmediatePropagation() –  Прерывает всплытие события по дереву –  Отменяет прочие обработчики http://www.w3.org/TR/DOM-Level-2-Events/46 events.html#Events-Event-stopPropagation
  46. 46. 47
  47. 47. Прерывание действия по умолчанию •  Действие по умолчанию –  Переход по ссылке –  Раскрытие <select> –  Сабмит формы –  Фокус в инпут –  Снятие фокуса •  event.preventDefault() –  Перерывает это действие •  Некоторые действия прервать нельзя –  var isCanPrevent = event.cancelable; –  resize, scroll, focus, error, load, unload, DOM*, … https://developer.mozilla.org/en-US/docs/DOM/48 event.preventDefault
  48. 48. Прерывание событий jQuery $(.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(); }); http://api.jquery.com/on/ 49 http://api.jquery.com/live/
  49. 49. Фильтрация событий debounce, throttle http://benalman.com/projects/jquery-throttle- debounce-plugin/
  50. 50. Бывает, что событий оченьмного, а обрабатыватькаждое дорого
  51. 51. throttle •  Фильтрация частоты сообщений •  Событие вызывается не чаще чем раз в N миллисекунд52
  52. 52. $.throttle(timeout, callback, no_trailing);53
  53. 53. $.throttle no_trailing=false Поток событий Пауза no_trailing=true Пауза Допущенные события54
  54. 54. $.throttle var log = $.throttle(250, function () { console.log(arguments); }); $(window).scroll(log); $(window).off(scroll, log); http://benalman.com/code/projects/jquery-throttle-55 debounce/examples/throttle/
  55. 55. debounce •  Склеивает вызовы в один •  Событие вызывается только после паузы в N милисекунд56
  56. 56. $.debounce(timeout, callback, at_begin);57
  57. 57. $.debounce at_begin=false Пауза at_begin=true Пауза58
  58. 58. $.debounce function suggest(event) {}; $(input).keyup(suggest); $(input).keyup($.debounce(250, suggest)); $(input).unbind(keyup, suggest); http://benalman.com/code/projects/jquery-throttle-59 debounce/examples/debounce/
  59. 59. Проблемы событийНеуместное использованиеНакладные расходы
  60. 60. События это круто –давайте вездеиспользовать!!1!
  61. 61. Событие геттер Вариант не удачного использования событий DataObject.on(someData, function (data) { console.log(data); }); DataObject.trigger(giveMe:someData);62
  62. 62. Y U NO63 DataObject.someData
  63. 63. События – поток. Их лучше использовать как поток данных64
  64. 64. Module A Module B65
  65. 65. Data C Module A Module B66
  66. 66. Data C Module A Module B Give me C67
  67. 67. Data C Data C Module A Module B Give me C68
  68. 68. Data C Data C Module A Module B Give me C69
  69. 69. Data C Data C Module A Module B70
  70. 70. Накладные расходы •  Событие – функция –  n объектов, k ресурсов = n*k функций –  функция занимает ресурсы –  лишние скоупы, сборка мусора и JIT-компиляция –  вызов кучи функций –  утечки памяти71
  71. 71. Events everywhere!
  72. 72. Не блокирующий I/O •  Дефрагментация времени блокировок –  Более плотная загрузка процесса •  Выгодно применять, когда время I/O больше времени обработки данных •  Меньше проблем с разделяемой памятью73
  73. 73. Слабое связывание •  Элементы не знают о программе •  Элементы общаются только событиями •  Меньше разделенной памяти –  Меньше проблем синхронизации74
  74. 74. trigger(message)! on(message, callback)!75
  75. 75. Заключение •  События –  PubSub –  Event Emitter –  Event Manager •  Фичи событий –  namespace –  накопление данных •  DOM события –  Event Bubbling –  Делегирование –  Прерывание события –  Отмена действия по умолчанию •  Фильтрация76
  76. 76. Михаил Давыдов Разработчик JavaScript azproduction@yandex-team.ru azproduction77 Спасибо

×