2012-04-20 39 views
5

有人可以告訴如何「取消綁定」匿名函數嗎? JQUERY它能夠做到這一點,但我怎樣才能在我自己的腳本中實現這個功能。取消綁定匿名函數

這是情景:

下面的代碼附加的「onClick」事件到DIV具有「someDivId」爲ID,現在聞您單擊DIV,它顯示「點擊!」。

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

這是所有偉大的,問題是如何「取消附加」功能的DIV如果函數是匿名的或如何「取消附加」所有連接事件的「a」元素?

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 2012-04-20 22:37:19

+0

你是否要求一個非基於jQuery的答案(例如純javascript)? – jfriend00 2012-04-20 22:38:32

+0

@ jfriend00:他想自己實現 - 例如。他不使用jQuery,而是問jQuery如何做。 – prodigitalson 2012-04-20 22:38:45

回答

4

最後,經過測試&錯誤的時間我已經找到了解決辦法,也許它不是最好的,最有效的。但它作品! (測試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天有用。

+1

我不確定''HELPERS.EVT [el]'行,其中'el'是對DOM元素的引用,正在執行您認爲正在執行的操作。 JavaScript屬性名稱[必須是字符串](https://developer.mozilla.org/en/JavaScript/Reference/Operators/Member_Operators#Property_names),我不確定DOM元素是否有標準的'toString'方法。在Firefox 11和IE9中,當在'div'元素上調用'toString'時,我得到''[object HTMLDivElement]「。 – 2012-04-21 19:52:00

+0

@CheranShunmugavel:完全正確。使用這個系統,兩個不同的'div'元素將在'HELPERS.EVT'表中顯示爲相同的屬性。 – 2012-04-22 00:29:52

2

個人(我知道這是不是「最好」的方式,因爲它需要我去思考我在做什麼),我喜歡使用正在處理的元素的on*事件屬性。

這有方便的快速和容易地分離事件的好處。

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

但是,您必須小心,因爲如果您嘗試添加第二個事件處理程序它將覆蓋第一個。記住這一點,你應該沒問題。

+0

a.onclick = null不起作用,這是因爲函數bindEvent()函數的方式不同,請檢查原始問題:我將編輯它的一個帖子bindEvent() – 2012-04-20 22:45:06

+0

的代碼感謝從jlaceda的想法我找到了解決問題的解決方案。 – 2012-04-21 03:29:25

-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事件系統的一小部分。它將如何回答這個問題? – 2012-04-20 23:05:50

+0

@jlaceda我正在檢查現在完整的源代碼。謝謝! – 2012-04-20 23:14:45

+0

@amnotiam我認爲這是jquery中事件刪除過程的「最裸機」部分,並且在創建自定義unBind函數時將是有用的參考。但你是對的,它不是一個完整的答案。我將在獨立函數中進行編輯,該函數將基於此片段。 – jlaceda 2012-04-20 23:34:20

1

我不知道你是否能解除綁定通過JavaScript附加一個匿名函數。如果可能,您可以簡單地從DOM中移除元素並重新創建它。這將消除以前附加的任何事件處理程序。

+0

但JQuery可以做到這一點!所以並非不可能! – 2012-04-20 23:13:19

+1

@JoshGuzman:jQuery爲每個元素綁定了一個*一個*處理程序,並且它從來就不是您傳遞它的處理程序。您的處理程序存儲在'jQuery.cache'中,它綁定一個通用的處理程序,該程序在調用時查看事件對象,查看它的類型,查找元素上的序列號,查看序列號存在於'jQuery.cache'中,如果是,則檢查是否給予當前事件類型的處理程序,如果是,則調用它/它們。 – 2012-04-20 23:28:08

+0

... jQuery綁定的通用處理程序也在'jQuery.cache'中引用,因此,當它解除綁定時,它會執行類似的查找,並將其傳遞給解除綁定處理程序的本機方法。當然,當你執行'.unbind('click')',它只是清除'jQuery.cache'中的'click'處理程序。 – 2012-04-20 23:30:10

1

JavaScript不提供附加到節點的事件偵聽器的列表。

您可以刪除一個節點的所有事件監聽器,但使用的Node.cloneNode方法,在這裏看到:https://developer.mozilla.org/En/DOM/Node.cloneNode

這個克隆節點(明顯),但它並不克隆附着的事件偵聽器。

你也只是結合空函數作爲事件偵聽器:

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

但我綁定到一個元素的函數是匿名的,這意味着我沒有名稱引用,所以我不能覆蓋它們或知道它們。 – 2012-04-20 23:55:31

+0

嗯,我忘了你可以有多個事件監聽器用於同一個事件。你不能得到你的匿名函數的參考。如果你可以改變你的代碼,使它不是匿名的,那將是最好的解決方案。否則,你只需要殺死所有的事件監聽器並重新添加你想要的。 – Griffin 2012-04-21 00:02:07

+0

問題解決,謝謝任何方式。 – 2012-04-21 03:26:36