2013-02-26 2 views
7

Я пишу инструмент vanilla 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

+1

Поскольку вы знаете, что jQuery может решить вашу проблему, вам просто нужно прочитать исходный код, как он работает. – pktangyue

+2

+1 по крайней мере, для смелости слова «ванильный JavaScript», а также выделение курсивом о jQuery! (Надеюсь, никто не будет предлагать jQuery в качестве решения сейчас ...) Но также +1, потому что это хороший вопрос. – guypursey

ответ

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

+0

Предоставляя функции слушателя глобальной переменной или одной в контексте, к которой вы можете получить доступ, где это необходимо, это можно решить. Например. 'window.listeners.myListener = function() {...}'. Таким образом, вы можете в любой момент сказать «elem.removeEventListener» («click», window.listeners.myListener) ' – marekful

+0

Я решил проблему, применив функции слушателя к arr [i]. Тогда я смог ссылаться на весь arr [ i], без необходимости передавать параметры слушателю. – tomturton

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

+1

Да, о котором вы ответили, во втором фрагменте кода для анонимной функции вы найдете то же самое: 'arr [i] .el.addEventListener ('click', function (arr [i ]) '... так что вы хотите передать как аргумент на самом деле? – Sandeep

+0

Аргумент должен быть' arr [i] 'в отличие от' arr [i] .el', к которому подключен слушатель. – tomturton

-1

Это можно сделать довольно легко, просто не так вы его прямо сейчас.

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

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); 
}); 

Это просто сокращенная версия того, что я написал ранее, но вы можете получить суть этого, я надеюсь.

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