2012-04-03 6 views
46

Voglio creare un eventoHandler che passa l'evento e alcuni parametri. Il problema è che la funzione non ottiene l'elemento. Ecco un esempio:gestore di eventi Javascript con parametri

doClick = function(func){ 
    var elem = .. // the element where it is all about 
    elem.onclick = function(e){ 
     func(e, elem); 
    } 
} 
doClick(function(e, element){ 
    // do stuff with element and the event 
}); 

L''elem' deve essere definito al di fuori della funzione anonima. Come posso ottenere l'elemento passato da usare all'interno della funzione anonima? C'è un modo per fare questo?

E per quanto riguarda addEventListener? Non riesco a passare l'evento attraverso un addEventListener?

Aggiornamento

mi sembrava di risolvere il problema con 'questo'

doClick = function(func){ 
    var that = this; 
    this.element.onclick = function(e){ 
     func(e, that); 
    } 
} 

Dove questo contiene this.element che posso accedere nella funzione.

addEventListener

ma mi chiedo circa l'addEventListener:

function doClick(elem, func){ 
    element.addEventListener('click', func(event, elem), false); 
} 
+1

Hai elem, elementi, elemento coinvolto nella sua interrogazione. Puoi essere meno confusionario? – mihai

+0

Mi dispiace, stavo cercando di fare un esempio della mia situazione ma questo non è andato bene, ho aggiornato il codice. – sebas2day

+0

Vuoi cercare 'e.target' /' e.currentTarget'? – Rolf

risposta

56

Non capisco esattamente ciò che il codice sta cercando di fare, ma si può rendere le variabili disponibili in qualsiasi gestore di eventi che utilizza i vantaggi delle chiusure di funzioni:

function addClickHandler(elem, arg1, arg2) { 
    elem.addEventListener('click', function(e) { 
     // in the event handler function here, you can directly refer 
     // to arg1 and arg2 from the parent function arguments 
    }, false); 
} 

A seconda del proprio esatto codice di codifica tu puoi quasi sempre fare una sorta di chiusura per preservare l'accesso alle variabili per te.

Dai vostri commenti, se quello che stai cercando di realizzare è questo:

element.addEventListener('click', func(event, this.elements[i])) 

Poi, si potrebbe fare questo con un auto si esegue la funzione (IIFE) che cattura gli argomenti che si desidera in una chiusura come esegue e restituisce l'attuale funzione di gestore di eventi:

element.addEventListener('click', (function(passedInElement) { 
    return function(e) {func(e, passedInElement); }; 
}) (this.elements[i]), false); 

Per maggiori informazioni su come funziona un IIFE, vedere questi altri riferimenti:

Javascript wrapping code inside anonymous function

Immediately-Invoked Function Expression (IIFE) In JavaScript - Passing jQuery

What are good use cases for JavaScript self executing anonymous functions?

Quest'ultima versione è forse più facile da vedere che cosa sta facendo in questo modo:

// return our event handler while capturing an argument in the closure 
function handleEvent(passedInElement) { 
    return function(e) { 
     func(e, passedInElement); 
    }; 
} 

element.addEventListener('click', handleEvent(this.elements[i])); 

E 'anche possibile utilizzare .bind() per aggiungere argomenti una richiamata. Qualsiasi argomento passato a .bind() verrà anteposto agli argomenti che avrà lo stesso callback. Quindi, si potrebbe fare questo:

elem.addEventListener('click', function(a1, a2, e) { 
    // inside the event handler, you have access to both your arguments 
    // and the event object that the event handler passes 
}.bind(elem, arg1, arg2)); 
+0

sì questo quasi quello che sto cercando di fare, ma cosa succede se la funzione anonima viene passata come parametro da addClickHandler e si vuole dare a questa funzione alcuni parametri con l'evento come: element.addEventListener ('click', func (evento , this.elements [i])); – sebas2day

+2

@ sebas2day: non è possibile eseguire 'element.addEventListener ('click', func (event, this.elements [i]))'. Javascript non funziona in questo modo. Ci sono altri modi per aggirare questo problema, usando le chiusure, ma non puoi farlo nel modo in cui hai scritto. addEventListener chiama la richiamata con esattamente un argomento (l'evento) e non è possibile modificarlo in alcun modo. – jfriend00

+0

Ho aggiunto un altro esempio di questo alla fine della mia risposta. – jfriend00

0

this all'interno del doThings è l'oggetto finestra.Prova questo invece:

var doThings = function (element) { 
    var eventHandler = function(ev, func){ 
     if (element[ev] == undefined) { 
      return; 
     } 

     element[ev] = function(e){ 
      func(e, element); 
     } 
    }; 

    return { 
     eventHandler: eventHandler 
    }; 
}; 
6

Qualcosa che puoi provare sta usando il metodo bind, penso che questo sia quello che stavi chiedendo. Se non altro, è ancora molto utile.

function doClick(elem, func) { 
    var diffElem = document.getElementById('some_element'); //could be the same or different element than the element in the doClick argument 
    diffElem.addEventListener('click', func.bind(diffElem, elem)) 
} 

function clickEvent(elem, evt) { 
    console.log(this); 
    console.log(elem); 
    // 'this' and elem can be the same thing if the first parameter 
    // of the bind method is the element the event is being attached to from the argument passed to doClick 
    console.log(evt); 
} 

var elem = document.getElementById('elem_to_do_stuff_with'); 
doClick(elem, clickEvent); 
2

Data l'aggiornamento alla domanda iniziale, sembra che ci sono problemi con il contesto ("questo") passando gestori di eventi. Le nozioni di base sono spiegate ad es. qui http://www.w3schools.com/js/js_function_invocation.asp

Una semplice versione di lavoro del vostro esempio potrebbe leggere

var doClick = function(event, additionalParameter){ 
    // do stuff with event and this being the triggering event and caller 
} 

element.addEventListener('click', function(event) 
{ 
    var additionalParameter = ...; 
    doClick.call(this, event, additionalParameter); 
}, false); 

Vedi anche Javascript call() & apply() vs bind()?

-1
let obj = MyObject(); 

elem.someEvent(function(){ obj.func(param) }); 

//calls the MyObject.func, passing the param. 
+0

In che modo questo risolve il problema dell'OP?Il parametro – RamenChef

+0

può anche essere una funzione di callback (nel contesto -say-global) e quindi può essere richiamata facilmente, con i parametri richiesti. –

1

Si tratta di una vecchia questione, ma un comune. Quindi lascia che aggiunga questo qui.

Con sintassi ES2015 si può raggiungere maniera più succinta:

function event_handler(event, arg) { 
    console.log(event, arg); 
} 

element.addEventListener('click', (event) => event_handler(event, 'Here comes the argument'));