2013-02-26 87 views
7

我正在編寫一個香草JavaScript工具,該工具在啓用時爲每個傳入的元素添加事件偵聽器。使用參數添加和刪除事件偵聽器

我願做這樣的事情:

var do_something = function (obj) { 
     // do something 
    }; 

for (var i = 0; i < arr.length; i++) { 
    arr[i].el.addEventListener('click', do_something(arr[i])); 
} 

不幸的是這不起作用,因爲據我所知,添加事件偵聽器時,參數只能傳遞到匿名函數

for (var i = 0; i < arr.length; i++) { 
    arr[i].el.addEventListener('click', function (arr[i]) { 
     // do something 
    }); 
} 

的問題是,我需要能夠當工具被禁止刪除事件偵聽器,但我不認爲這是可能移除事件偵聽器與ANO nymous功能

for (var i = 0; i < arr.length; i++) { 
    arr[i].el.removeEventListener('click', do_something); 
} 

我知道我可以很容易地使用jQuery來解決我的問題,但我試圖儘量減少依賴性。 jQuery必須以某種方式繞過此代碼,但代碼有點像叢林!

+1

所以命名你的監聽器,然後你可以使用'removeEventListener'。 – marekful 2013-02-26 11:33:17

+1

既然你知道jQuery可以解決你的問題,你只需要閱讀源代碼是如何工作的。 – pktangyue 2013-02-26 11:41:02

+2

+1至少爲粗體字「vanilla JavaScript」加上斜體並且表示jQuery! (希望沒有人會實際上建議jQuery作爲解決方案,現在...)但也+1,因爲這是一個很好的問題。 – guypursey 2013-02-26 11:43:20

回答

8

這是無效:

arr[i].el.addEventListener('click', do_something(arr[i])); 

偵聽必須是一個函數參考。您無法在偵聽器分配時指定參數。處理程序函數將始終被調用,event作爲第一個參數傳遞。要通過其他參數,你可以用你的聽衆進入一個匿名函數,像這樣:

elem.addEventListener('click', function(event) { 
    do_something(...) 
} 

爲了能夠通過removeEventListener刪除自己剛命名處理函數:

function myListener(event) { 
    do_something(...); 
} 

elem.addEventListener('click', myListener); 

要訪問其他變量在處理函數中,你可以使用閉包。例如:

function someFunc() { 
    var a = 1, 
     b = 2; 

    function myListener(event) { 
    do_something(a, b); 
    } 

    elem.addEventListener('click', myListener); 
} 
+0

這很好,當我不需要刪除監聽程序或在與someFunc()相同的作用域中刪除它時。不幸的是,情況並非如此(儘管也許應該是這樣) – tomturton 2013-02-26 11:49:01

+0

通過使偵聽器函數成爲一個全局變量或一個可以從需要的地方訪問的環境變量,可以解決這個問題。例如。 'window.listeners.myListener = function(){...}'。這樣你可以隨時說'elem.removeEventListener('click',window.listeners.myListener)' – marekful 2013-02-26 11:55:09

+0

我通過將監聽器函數應用於arr [i]解決了這個問題。然後我可以引用整個arr [我]對象,而不需要傳入參數給偵聽器。 – tomturton 2013-03-05 16:45:47

0

您可以使用

for (var i = 0; i < arr.length; i++) { 
    arr[i].el.addEventListener('click', do_something); 
} 

隨着事件被傳遞到do_something功能第一個參數,你可以從該事件的元素作爲

function do_something(e) { 
    var obj = e.currentTarget 
    // do something 
} 

刪除監聽

for (var i = 0; i < arr.length; i++) { 
    arr[i].el.removeEventListener('click', do_something); 
} 

,如果你想通過其他的obj作爲參數做到這一點

for (var i = 0; i < arr.length; i++) { 
    arr[i].el.addEventListener('click', do_something, obj); 
} 
+0

不幸的是,e.currentTarget實際上會指向arr [i] .el – tomturton 2013-02-26 11:51:35

+1

是的,你已經在第二個代碼片段中發佈了相同的匿名函數'arr [i] .el.addEventListener('click',function(arr [i ])'...所以你想作爲參數實際傳遞什麼? – Sandeep 2013-02-26 12:00:55

+0

參數需要是'arr [i]'而不是'arr [i] .el'這是監聽器所連接到的 – tomturton 2013-02-26 14:23:21

-1

這可以很容易做到,只要不是因爲你擁有它現在。

而不是嘗試添加和刪除隨機anonymouse函數,您需要添加或刪除一個函數來處理您的其他函數的執行。

var 
    // Here we are going to save references to our events to execute 
    cache = {}, 

    // Create a unique string to mark our elements with 
    expando = String(Math.random()).split('.')[ 1 ], 

    // Global unique ID; we use this to keep track of what events to fire on what elements 
    guid = 1, 

    // The function to add or remove. We use this to handler all of other 
    handler = function (event) { 

     // Grab the list of functions to fire 
     var handlers = (cache[ this[ expando ] ] && cache[ this[ expando ] ][ event.type ]) || false; 

     // Make sure the list of functions we have is valid 
     if (!handlers || !handlers.length) { 
      return; 
     } 

     // Iterate over our individual handlers and call them as we go. Make sure we remeber to pass in the event Object 
     handlers.forEach(function (handler) { 
      handler.call(this, event); 
     }); 

    }, 

    // If we want to add an event to an element, we use this function 
    add = function (element, type, fn) { 

     // We test if an element already has a guid assigned 
     if (!element[ expando ]) { 
      element[ expando ] = guid++; 
     } 

     // Grab the guid number 
     var id = element[ expando ]; 

     // Make sure the element exists in our global cache 
     cache[ id ] = cache[ id ] || {}; 

     // Grab the Array that we are going to store our handles in 
     var handlers = cache[id ][ type ] = cache[ id ][ type ] || []; 

     // Make sure the handle that was passed in is actually a function 
     if (typeof fn === 'function') { 
      handlers.push(fn); 
     } 

     // Bind our master handler function to the element 
     element.addEventListener(type, handler, false); 

    }; 

// Add a click event to the body element 
add(document.body, 'click', function (event) { 
    console.log(1); 
}); 

這只是我之前寫的內容的減少版本,但您可以獲得它的要點。