2012-04-20 3 views
5

Может кто-нибудь сказать, как «отвязать» анонимную функцию? JQUERY он способен это сделать, но как я могу реализовать эту Функциональность в своем собственном скрипте.Отменить анонимную функцию

Это сценарий:

Следующий код прикрепить «OnClick» событие в Div, которые имеют «someDivId», как ID, теперь вэнь вы щелкните DIV, это шоу «щелкнул!».

var a = document.getElementById('someDivId'); 
bindEvent(a,'click',function(){alert('clicked!');}); 

Это все замечательно, проблема заключается в том, чтобы «не-пристроить» функции в DIV, если функция является анонимным или как «не-подключить» все подключенные к нему события к «а» элемент?

unBind(a,'click'); //Not necessarily the given params, it's just an example. 

Это код для метода bindEvent:

function bindEvent (el,evtType,fn){ 
    if (el.attachEvent) { 
     el['e'+evtType+fn] = fn; 
     el[evtType+fn] = function(){ 
      fn.call(el,window.event); 
     } 
     el.attachEvent('on'+evtType, el[evtType+fn]); 
    } else { 
     el.addEventListener(evtType, fn, false); 
    } 
} 
+1

Где вы взяли 'bindEvent()'? Что оно делает? – jfriend00

+0

Вы запрашиваете не-jQuery-ответ (например, простой javascript)? – jfriend00

+0

@ jfriend00: он хочет реализовать его самостоятельно - например. ГЭС не использует jQuery, но спрашивает, как это делает jQuery. – prodigitalson

ответ

4

Наконец, и после нескольких часов испытаний & ошибок я нашел решение, может быть, это не самый лучший и самый эффективный, но ... IT РАБОТАЕТ! (Протестировано на IE9, Firefox 12, Chrome 18)

Во-первых, я создаю два кросс-браузера и вспомогательные методы addEvent() и removeEvent(). (Идея взята из исходного кода JQuery!)

HELPERS.removeEvent = document.removeEventListener ? 
function(type, handle,el) { 
    if (el.removeEventListener) { 
    //W3C Standard  
    el.removeEventListener(type, handle, true); 
    } 
} : 
function(type, handle,el) { 
    if (el.detachEvent) { 
     //The IE way 
     el.detachEvent('on'+type, el[type+handle]); 
     el[type+handle] = null; 
    } 
}; 

HELPERS.addEvent = document.addEventListener ? 
function(type, handle,el) { 
    if (el.addEventListener) { 
     //W3C Standard 
     el.addEventListener(type, handle, true); 
    } 
} : 
function(type, handle,el) { 
    if (el.attachEvent) { 
     //The IE way 
     el['e'+type+handle] = handle; 
     el[type+handle] = function(){ 
      handle.call(el,window.event); 
     }; 
     el.attachEvent('on'+type, el[type+handle]); 

    } 
} 

Также нужен какой-то «контейнера» для хранения прикрепленных событий к элементам, например:

HELPERS.EVTS = {}; 

И, наконец, два вызываемая и экспонировали на методы пользователей: СЛЕДУЮЩЕЮ один для добавления события (события) и связать это событие с методом (обработчиком) для определенного элемента (el).

function bindEvent(event, handler,el) { 

      if(!(el in HELPERS.EVT)) { 
       // HELPERS.EVT stores references to nodes 
       HELPERS.EVT[el] = {}; 
      } 

      if(!(event in HELPERS.EVT[el])) { 
       // each entry contains another entry for each event type 
       HELPERS.EVT[el][event] = []; 
      } 
      // capture reference 
      HELPERS.EVT[el][event].push([handler, true]); 
      //Finally call the aux. Method 
      HELPERS.addEvent(event,handler,el); 

     return; 

    } 

Наконец метод, который не-присоединять каждое предварительно приложенное событие (события) для конкретного элемента (EL)

function removeAllEvent(event,el) { 

      if(el in HELPERS.EVT) { 
       var handlers = HELPERS.EVT[el]; 
       if(event in handlers) { 
        var eventHandlers = handlers[event]; 
        for(var i = eventHandlers.length; i--;) { 
         var handler = eventHandlers[i]; 
         HELPERS.removeEvent(event,handler[0],el); 

        } 
       } 
      } 

    return; 

    } 

Кстати, называть это методами, которые вы должны сделать следующее: Захват более DOM Узел

var a = document.getElementById('some_id'); 

Вызвать метод 'bindEvent()' с соответствующими параметрами.

bindEvent('click',function(){alert('say hi');},a); 

И де-присоедините его:

removeAllEvent('click',a); 

Вот и все, надеюсь, будет полезным для кого-то один день.

+1

Я не уверен, что строка 'HELPERS.EVT [el]', где 'el' является ссылкой на элемент DOM, делает то, что, по вашему мнению, делает. Имена свойств JavaScript [должны быть строками] (https://developer.mozilla.org/en/JavaScript/Reference/Operators/Member_Operators#Property_names), и я не уверен, что существует стандартный метод toString для элементов DOM. В Firefox 11 и IE9 я получаю '' [object HTMLDivElement] "' ​​при вызове 'toString' в элементе' div'. –

+0

@CheranShunmugavel: Это точно. Используя эту систему, два разных элемента 'div' будут отображаться как одно и то же свойство в таблице' HELPERS.EVT'. –

2

лично (и я знаю, что это не «лучший» способ, так как это требует меня думать о том, что я делаю), Мне нравится просто использовать свойства события on* элемента, с которым я работаю.

У этого есть удобный потенциал для быстрого и легкого отсоединения событий.

var a = document.getElementById('someDivId'); 
a.onclick = function() {alert("Clicked!");}; 
// later... 
a.onclick = null; 

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

+0

a.onclick = null не работает, потому что функция bindEvent() работает по-другому, пожалуйста, проверьте исходный вопрос: я собираюсь отредактировать это сообщение кодом bindEvent() –

+0

, благодаря идея из jlaceda я нашел решение для решения проблемы. –

-1

Это из JQuery-х source:

jQuery.removeEvent = document.removeEventListener ? 
    function(elem, type, handle) { 
     if (elem.removeEventListener) { 
      elem.removeEventListener(type, handle, false); 
     } 
    } : 
    function(elem, type, handle) { 
     if (elem.detachEvent) { 
      elem.detachEvent("on" + type, handle); 
     } 
    }; 
+2

Это всего лишь небольшая часть системы событий jQuery. Как он ответит на вопрос? –

+0

@jlaceda Я проверяю теперь полный исходный код. спасибо! –

+0

@amnotiam Я понял, что это «самая голодная металлическая» часть процедуры удаления события в jquery и будет полезной ссылкой при создании пользовательской функции unBind. Но вы правы, что это не полный ответ. Я отредактирую в автономной функции, которая будет основана на этом фрагменте. – jlaceda

1

Я не уверен, если вы можете отвязать анонимную функцию, прикрепленную с помощью JavaScript. Если возможно, вы можете просто удалить элемент из DOM и воссоздать его. Это избавит вас от каких-либо ранее обработанных обработчиков событий.

+0

, но JQuery может это сделать! так что это не невозможно! –

+1

@JoshGuzman: jQuery связывает ровно * one * обработчик на элемент, и это никогда не обработчик, который вы его передали. Ваши обработчики хранятся в 'jQuery.cache'. Он связывает общий обработчик, который при вызове, смотрит на объект события, видит, какой тип события он ищет, просматривает серийный номер элемента, смотрит, будет ли этот серийный номер существует в 'jQuery.cache', и если да, то проверяет, были ли обработаны какие-либо обработчики для текущего типа события и вызывает ли он/их, если это так. –

+0

... общий обработчик, связанный с jQuery, также упоминается в 'jQuery.cache', поэтому, когда приходит время его отменить, он выполняет аналогичный поиск и передает его собственным методам, которые отключают обработчики. Конечно, когда вы делаете '.unbind ('click')', это просто очищает обработчики 'click' в' jQuery.cache'. –

1

JavaScript не предоставляет список прослушивателей событий, прикрепленных к узлу.

Вы можете удалить все обработчики событий для узла, но с использованием метода Node.cloneNode, смотрите здесь: https://developer.mozilla.org/En/DOM/Node.cloneNode

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

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

function noop() {} 
bindEvent(myElement, "click", noop); 
+0

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

+0

Ах, да, я забыл, что у вас может быть несколько слушателей событий для одного и того же мероприятия. Вы не можете получить ссылку на свою анонимную функцию. Если вы можете изменить свой код, чтобы он не был анонимным, это было бы лучшим решением. В противном случае вам просто нужно будет убить всех прослушивателей событий и добавить те, которые вы хотите, снова. – Griffin

+0

проблема решена, спасибо любым способом. –

Смежные вопросы