События Jquery Изнутри

Статья написана в рамках конкурса среди студентов.

Технопарк Мейл.

ру .



События jQuery изнутри

Думаю, библиотека jQuery JavaSript не нуждается в представлении, но на всякий случай напомню, что jQuery призван ускорить разработку, обеспечить синтаксический «сахар» для нативного js и избавить разработчиков от проблем, связанных с кроссплатформенностью.

Прежде чем мы поговорим о том, как работает обработка событий в jQuery, мы не можем не упомянуть историю обработки событий в браузере.

Обработка событий в js Давайте немного вспомним историю браузеров.

Это были уже далекие 90-е; Internet Explorer еще не был самым распространенным браузером, но господствовал Netscape Navigator. Именно разработчики «Навигатора» предложили первую модель обработки событий на js (сейчас эту модель чаще всего называют DOM Level 0 Event Model).



Модель событий DOM уровня 0
Данная модель характеризуется следующими основными факторами:
  • Ссылка на функцию-обработчик записывается непосредственно в свойство dom-объекта.

    Названия всех событий имеют приставку «on» — onclick, onload и т.д.

  • Все параметры события передаются обработчику в форме объекта события в качестве первого аргумента во всех браузерах, кроме IE. В нем параметры находятся в window.event.
  • События могут подниматься от узла, в котором они происходят, к родителю, затем к родителю родителя и так далее.

    Этот процесс обычно называют фазой восхождения.

  • Невозможно установить несколько обработчиков для одного и того же события в элементе.

Функцию-обработчик можно присвоить свойству DOM-элемента как в js-скрипте, так и непосредственно в HTML-разметке:
Скрипт HTML
  
  
  
  
   

var element = document.getElementById('id'); element.onmousemove = function (e) { /* … */ };



<a onclick="return{'b-link':{}}" >.

</a> <body onresize="onBodyResize()" >.

</body>

Стоит отметить, что хотя эта модель не стандартизирована W3C, она поддерживается всеми современными браузерами (по крайней мере, на настольных компьютерах).

И эта модель используется до сих пор.

Примеры (HTML) взяты с yandex.ru и vk.com. Модель проста как три копейки, но жизнь не стоит на месте.



Модель событий DOM уровня 2


События jQuery изнутри

В 2000 году W3C выпустил спецификацию.

Модель событий DOM уровня 2 , который можно охарактеризовать следующим образом:

  • установка обработчика методом addEventListener (удаление с помощью RemoveEventListener);
  • префикс on не используется в именах событий;
  • Объект события аналогичен модели событий DOM уровня 0;
  • неограниченное количество слушателей одного и того же события на элементе;
  • фаза восхождения из модели событий DOM уровня 0;
  • Добавлен этап предварительного захвата, на котором событие спускается от корневого элемента дерева DOM до элемента, в котором произошло событие.

Метод регистрации для обработки имеет следующий синтаксис addEventListener(eventType, Listener, [useCapture=true]):
  • eventType — тип события («клик», «изменение» и т. д.);
  • прослушиватель — ссылка на функцию-обработчик;
  • useCapture — булева переменная, определяющая, на какую фазу мы подписываемся (true — захват, false — всплытие).

Тогда подписка на изменение размера окна браузера будет выглядеть так:

window.addEventListener('resize', function (event) { /* … */ });



Модель событий Internet Explorer
Разработчики из Microsoft всегда шли своим путем и до версии IE 9 не поддерживали общепринятую модель событий, но у них была своя, с блэкджеком atachEvent и detachEvent. Эта модель похожа на модель событий DOM Level 2, но имеет ряд отличий (есть и множество других, но это самые основные):
  • методы AttachEvent и detachEvent для установки и удаления обработчиков соответственно;
  • префикс «on» в названиях событий;
  • отсутствие фазы захвата.



Нижняя граница
Учитывать различия между браузерами мучительно больно, но в этом нет необходимости! Не забывайте, что все эти проблемы встречались и до нас — в частности, поэтому появилась библиотека jQuery.

Обработка событий с помощью jQuery

Здесь и далее под jQuery мы будем подразумевать jQuery 1.10.2, текущую версию из ветки 1.0. Когда мы используем jQuery, мы можем смело забыть о различиях между addEventListener и AttachEvent и многом другом, ведь библиотека предоставляет разработчику следующее:
  • унифицированный способ регистрации обработчиков событий (с помощью методов);
  • неограниченное количество обработчиков одного и того же события на одном элементе;
  • передача нормализованного объекта события обработчику.

Итак, в jQuery есть множество методов, с помощью которых можно подписаться на обработку событий:
  • связывать — устанавливает обработчик непосредственно для элемента(ов).

    Принимает имя события и обратный вызов в качестве аргументов;

  • щелкнуть , размытие , прокрутка и многие другие методы быстрого доступа аналогичны вызову привязки, только типом события является имя самого метода;
  • на — метод main позволяет как привязать обработчик непосредственно к элементу, так и делегировать обработку событий; Для делегирования необходимо передать необязательный параметр селектора;
  • делегат — псевдоним метода on с измененным набором аргументов;
  • один — то же, что и метод on, но обработчик сработает только при первом возникновении события.

Отписаться от мероприятия можно тремя способами: развязать (для привязки, клика и т.п.

), неделегировать И выключенный .

Но…

События jQuery изнутри

jQuery не только предоставляет нам уровень абстракции от addEventListener и AttachEvent, но и не только нормализует объект Event. Под капотом jQuery скрывается огромный слой кода, состоящий из:

  • шаблон проектирования наблюдатель , реализующий логику централизованной установки/удаления обработчиков событий;
  • система перехватов и фильтрации параметров для Event Object;
  • а также возможность расширения функциональности jQuery.event с помощью API специальных событий .

Перво-наперво.



jQuery.event

Многие люди уже обсуждали, как работает jQuery изнутри (например, здесь ), но по каким-то причинам механизм обработки событий был обойден.

Итак, давайте восполним этот пробел.

Обработка событий с точки зрения пользователя библиотеки проходит три этапа:

  1. установка обработчика событий — вызов метода привязки и т.д.
  2. обработка событий — вся магия, которую ранее совершает jQuery до момента, когда он передаст нормализованный Event Object «нашему» обработчику;
  3. удаление обработчика событий - вызов метода unbind и т.д.


API специальных событий
Библиотека jQuery дает стороннему коду возможность влиять на обработку событий.

В недрах библиотеки есть объект jQuery.event.special; его ключи — это названия событий, в обработку которых мы хотим вмешаться, а значением может быть объект со следующими свойствами:

  • нетпузырь — флаг, определяющий, должно ли событие всплывать при вызове метода триггера.

    По умолчанию — false (событие всплывает).

    В самой библиотеке используется для проведения мероприятий нагрузка чтобы событие загрузки на картинках не всплывало перед окном.

  • тип привязки, тип делегата (строка) позволяет изменить тип обрабатываемого события.

    Например, события реализуются с использованием этого в jQuery. мышьвведите/отпустите мышь через стандартное наведение курсора мыши/наведение мыши.

  • настраивать — функция вызывается, когда обработчик этого типа впервые устанавливается на элемент.
  • срывать Вызывается, когда из элемента удаляется последний обработчик данного типа.

  • добавлять - функция вызывается всякий раз, когда добавляется обработчик.

  • удалять Вызывается всякий раз, когда удаляется обработчик.

  • ручка будет вызываться всякий раз, когда происходит событие, вместо обработчика, передаваемого методу on (или привязке, one и т. д.).

    Использование этого специального метода хорошо представлено в официальная страница .

Можно как вмешиваться в механизм обработки существующих событий, так и создавать свои.

Вот как вы можете создать pushy-событие, которое будет реагировать на стандартный щелчок:

jQuery.event.special.pushy = { bindType: "click", delegateType: "click" };

Помимо вышеперечисленных, возможны и другие свойства, о назначении которых можно прочитать на соответствующем страница .

Далее в статье мы покажем, в какие моменты jQuery передает управление тем или иным специальным методам, и как именно вы можете влиять на ход обработки событий.



Установка обработчика


События jQuery изнутри

Представим, что мы выполняем код

$('div').

click(function (e) { /* .

*/ });

вместе с jQuery. Давайте посмотрим, что происходит на каждом этапе.

Внешний обработчик .

Чтобы обработать событие, вам необходимо создать обработчик, получить на него ссылку и передать ее любому методу jQuery, отвечающему за установку обработчика.

На самом деле мы создали функцию, используя fucntion (e) { /* .

*/ }, и вызвали метод click, используя ее в качестве параметра.

Методы привязка, один, делегат и т. д. Наш обработчик попадает в один из этих методов, внутри которого с другим набором параметров.

Фактически метод включен.

Метод на состоит из солидного набора блоков if-else — обрабатываются и упорядочиваются все возможные варианты параметров, с которыми его можно вызвать.

Также именно в методе on реализована логика установки однократно срабатывающий обработчик (способ первый).

Наконец, каждый метод вызывается для текущего объекта jQuery. Метод каждый — часть ядра jQuery, именно с помощью этого метода библиотека перебирает «набор jQuery» (см.

здесь ).

Каждый метод может обрабатывать массивы и объекты в зависимости от предоставленного интерфейса.

Если объект предоставляет свойство длины, он повторяется так же, как массив, что является отличным примером микрооптимизации.

Итак, для каждого элемента DOM в наборе jQuery вызывается метод add. Вся последующая обработка происходит в методе добавлять (из объекта jQuery.event).

Вначале каждому внешнему обработчику назначается уникальный идентификатор .

Для этого (и не только) в jQuery есть глобальный счетчик jQuery.guid, который увеличивается при каждом использовании.

Затем создается функция, которую в дальнейшем мы будем вызывать главный обработчик , который принимает объект события в качестве входных данных и вызывает метод отправки.

Если обработчик этого события для данного элемента устанавливается впервые, то очередь обработчика (в него будут записаны все внешние обработчики) и вызывается Special.setup, если он указан для данного типа событий.

Внутри специальная.

настройка разработчик может реализовать свою собственную логику создания основного обработчика и подписки на событие с помощью функций addEventListener или AttachEvent, либо какой-либо другой независимой логики.

Далее созданный обработчик mainr подписывается на нужное событие с помощью методов addEventListener или atachEvent, в зависимости от браузера, но это происходит только в том случае, если специальный.

setup не указан или возвращает false. Затем управление передается специальный.

добавить , если это указано.

В отличие от Special.setup, Special.add выполняется всякий раз, когда обработчик устанавливается через jQuery. И после всего этого внешний обработчик, переданный в самом верху, попадает в очередь обработчиков( связь ) и будет вызываться при возникновении события.

Подробнее об этом позже.



Обработка событий


События jQuery изнутри

происходит событие — событие происходит в DOM-элементе и переходит в созданный библиотекой главный обработчик (он подписывается на событие с помощью addEventListener или AttachEvent), в котором вызывается метод отправки.

В методе отправлять параметром события будет исходный ненормализованный объект события, который передается методу исправить для нормализации.

Внутри метода fix проверяется, что Объект события не готов? (проводилась ли нормализация ранее), а если нет, то:

  • Проверяет, есть ли fixHooks[тип] , где тип — тип произошедшего события.

    fixHooks[тип] — это объект, который может иметь два свойства:

    • props — массив имен свойств, который необходимо скопировать из исходного объекта события в нормализованный;
    • фильтр — функция, которая нормализует (преобразовывает) параметры события.

  • Если есть fixHooks определенного типа, то используется этот объект; если нет, то с помощью спец.

    регулярное выражение проверяет, является ли наше событие событием клавиши или событием мыши (каждый из этих типов имеет свои fixHooks — ключКрючки И мышьКрючки соответственно).

  • Затем создается «пустой» нормализованный объект события (с использованием новый jQuery.Event ) и все свойства, имена которых присутствуют в массивах jQuery.event.props и fixHooks.props, скопировано из исходного объекта события в нормализованный.

    В конце метода fix вызывается функция фильтр , если он определен, и нормализованный объект события возвращается обратно в отправку.

Затем позвонил специальный.

preDispatch , в зависимости от его результата, дальнейшая обработка события может завершиться (если preDispatch вернет false).

После этого для каждого обработчика из очереди, созданной на этапе установки, вызывается специальный.

обработчик , если он есть.

Если его нет, то обработчик вызывается напрямую внешний обработчик ( связь ).

В конце метода отправки, после запуска всех обработчиков, он вызывается специальный.

postDispatch .

Метод Special.postDispatch также можно определить в вашем коде, как и другие специальные методы.



Удаление обработчика
Удаление обработчика проходит этапы, аналогичные этапам установки, а именно: удаление, начиная, например, с развязать , так или иначе попадает в метод выключенный , затем jQuery перебирает набор, используя каждый , и в конце вызывается не метод add, а метод удаления (спасибо, Кэп).

В методе удалять (из jQuery.event) по отношению к методу add выполняются противоположные операции:

  • Внешний обработчик ищется в очереди обработчиков по идентификатору.

    Затем внешний обработчик удаляется из очереди.

  • Если очередь пуста, то она также удаляется, как и основной обработчик с помощью jQuery.removeEvent , который, в свою очередь, также является оберткой для removeEventListener и detachEvent.
На процесс удаления обработчика можно повлиять путем определения функций специальный.

удалить И специальный.

снос .

Remove вызывается всякий раз, а демонтаж вызывается, когда очередь пуста.



Нижняя граница

Мы вспомнили, как обрабатываются события в браузере, что происходит с клиентским js-кодом при выходе на арену jQuery и что происходит внутри этой библиотеки.

Единый основной обработчик элемента, нормализация Event Object посредством копирования и фильтрации, очередь обработчиков событий и зоопарк методов установки — это реализация паттерна Observer, которую нам подарили создатели jQuery. По крайней мере, такие важные темы для Events, как делегирование, PreventDefault(), stopPropagation(), триггер и пространства имен остались позади.

Но только исходный код может рассказать обо всем.

Так github ожидающий.

:) Теги: #JavaScript #jQuery #события jquery #новички

Вместе с данным постом часто просматривают: