Где хранятся прикрепленные обработчики событий «метаданные»? На объекте "DOM" или ...? - PullRequest
8 голосов
/ 03 февраля 2012

Мне всегда было интересно ... поэтому у вас есть такой код:

$('#click-me');

и вы прикрепите это с помощью:

$('#click-me').click(someFunction);

где «метаданные», которые говорят:

«Привет» jQuery-object # click-me, «Я укажу вам на« someFunction », когда вы нажмете!»

Я знаю, что обработчики событий могут быть уничтожены, например, моя ситуация с Backbone.js, где мои события перестали срабатывать из-за того, что я заново рендерил всю страницу, уничтожая некоторые фоновые функции / объекты / представления по пути .. (это контекст того, почему я задаю этот вопрос)

СЕЙЧАС МОЙ ВОПРОС :

где хранятся «метаданные» событий и как они уничтожаются? Они хранятся в функции, которая связывает их с функцией? Находятся ли они в мета-данных DOM (если они есть)?

Я пытаюсь изучить тонкости JavaScript, потому что устал от ошибок. В дополнение к этому, мне интересно, стоит ли мне следить за сборкой мусора, которая может отключить мои события и тому подобное. Исходя из C #, я бы сказал, что JavaScript с DOM - это действительно что-то ...

(также, как примечание, как я могу получить доступ к этим событиям и «отладить» их? Firefox? Chrome?)


UPDATE

Иными словами, где хранится информация, которая связывает элемент DOM с определенным событием? DOM? Объекты? (или .. jQuery отображает это? есть ли в JavaScript «метаданные»? он находится вокруг этого контекста ..

Ответы [ 4 ]

5 голосов
/ 03 февраля 2012

Обновление : Итак, я неправильно понял вопрос, вы хотели знать, как события связаны в контексте только javascript и html.Мой оригинальный ответ ниже описывает, как jquery создает события и управляет ими.Это сводится к вызову element.addEventListener .

Из документов MDN вы видите, что цель события может быть элементом , документом , , окном или XMLHttpRequest .Из спецификаций w3 для событий DOM цель события добавляет, удаляет и отправляет событие.Таким образом, даже информация, вероятно, хранится во всех инкапсулирующих вещах, таких как элементы, это будет реализовано на уровне браузера.

Из проблемы, о которой вы упоминали, о копировании и последующей замене htmlиз тела стирает события , я думаю, что браузер просто дает вам разметку (без метаданных события), а затем, когда вы заменяете ее, метаданные исчезают.(http://jsfiddle.net/qu9bF/1/)


Оригинальный ответ : Как работают обработчики событий jquery.

Хорошо, поэтому я начал копать это для JQuery 1.4.2 (потому что у меня былоиспользовать несколько инструментов, которые не обновляются)

Сначала посмотрите на это: http://james.padolsey.com/jquery/#v=1.4.2&fn=click

function (fn) {
    return fn ? this.bind(name, fn) : this.trigger(name);
}

Вот как определяется , это на самом деле не определено в коде. JQuery определяет эту функцию для всех событий / функций-обработчиков, как показано ниже, да! Они динамически созданы / определены :

jQuery.each( ("blur focus focusin focusout load resize scroll unload click
            dblclick " +
        "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
        "change select submit keydown keypress keyup error").split(" "), 
    function( i, name ) {
        // the magic happens here..
        //each string is added as a function to the prototype
        jQuery.fn[ name ] = function( fn ) {
                return fn ? this.bind( name, fn ) : this.trigger( name );
        };//if a handler is NOT specified then attach an event OR call/trigger it

        if ( jQuery.attrFn ) {
                jQuery.attrFn[ name ] = true;
        }
});

ОтсюдаТеперь нам нужно взглянуть на связывание, теперь bind() и one() также определены следующим образом. Поиск «Код: связывание и одно событие» здесь

Отсюда я использовал chrome с этой скрипкой http://jsfiddle.net/qu9bF/ для перехода к коду. Блок из c.each(["bind" определяет функцию связывания. Источник минимизирован, но chrome может отформатировать его .

enter image description here

Отсюда по коду звонков JQuery.events.add вы можете найти его в разделе «События» здесь .Это не add(), что задокументировано, я думаю

Внизу, этот кусок кода - то, что делает волшебство.Соответственно он вызывает element.addEventListener или attachEvent .Посмотрите, как это добавляет на для attachEvent.

// Check for a special event handler
// Only use addEventListener/attachEvent if the special
// events handler returns false
if ( !special.setup || 
      special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
      // Bind the global event handler to the element
       if ( elem.addEventListener ) {
             elem.addEventListener( type, eventHandle, false );

        } else if ( elem.attachEvent ) {
             elem.attachEvent( "on" + type, eventHandle );
        }
 }

И вот оно у вас!:) Я надеюсь, что он ответил на оба ваших вопроса.Вы можете связать с не минимизированными версиями исходного кода jquery и пройтись по нему, чтобы разобраться.IMO иногда отладчик IE9 более интуитивен (это единственное, для чего я его использую), и использую страницы, которые я упомянул, для разумного просмотра источника.

2 голосов
/ 03 февраля 2012

Обычные события, такие как click или submit (если они не связаны jQuery), фактически являются просто свойствами ('onclick', 'onsubmit') самих элементов DOM.

Для событий jQuery библиотека сохраняет своизапись, когда вы связываете их и смотрит на него, когда вы их запускаете.jQuery помещает все данные об элементах в стандартное место, к которому вы можете получить доступ $(e).data().Для событий это просто $(e).data('events').

. Вы можете отсоединить события jQuery с помощью $().unbind(), а обычные события - с помощью ключевого слова delete, чтобы удалить свойство объекта, соответствующее данному событию.

2 голосов
/ 03 февраля 2012

jQuery сохраняет всю привязку событий и кэш данных в объекте jQuery.cache.Все узлы DOM, которые были обернуты с помощью jQuery и с которыми связаны события или набор данных, будут автоматически очищены при использовании jQuery html, empty, remove, replace и т. Д.Вот почему очень важно никогда не использовать innerHTML или другие собственные методы DOM для вставки / замены содержимого, которое было изменено ранее с помощью jQuery.Это приведет к утечкам , которые вы не сможете очистить, если не сбросите объект jQuery.cache вручную.

Существует также недокументированный метод jQuery.cleanData, который принимает коллекциюУзлы DOM в качестве аргумента, итерирует по ним, очищает все их привязки событий, данные и удаляет ссылки на эти элементы из кэша.Это может быть полезно, если у вас есть фрагменты DOM, которые были отделены от основного дерева DOM, и есть риск, что они не будут очищены должным образом.

0 голосов
/ 03 февраля 2012

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

...