2012-04-03 19 views
46

Chcę utworzyć eventHandler, który przekazuje zdarzenie i niektóre parametry. Problem polega na tym, że funkcja nie otrzymuje elementu. Oto przykład:Obsługa zdarzeń JavaScript z parametrami

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

"elem" musi być zdefiniowany poza anonimową funkcją. Jak mogę uzyskać przekazany element do użycia w funkcji anonimowej? Czy jest jakiś sposób na zrobienie tego?

A co z addEventListener? Wydaje mi się, że nie jestem w stanie przekazać zdarzenia przez addEventListener w ogóle ja?

Aktualizacja

wydawało mi się rozwiązać problem z 'tego'

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

Gdzie ten zawiera this.element, że można uzyskać dostęp do funkcji.

addEventListener

Ale zastanawiam addEventListener:

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

Masz elem, elementy, element zaangażowany w swoim pytaniu. Czy możesz być mniej kłopotliwy? – mihai

+0

Przykro mi, próbowałem zrobić przykład mojej sytuacji, ale to nie poszło dobrze, zaktualizowałem kod. – sebas2day

+0

Szukasz "e.target' /' e.currentTarget'? – Rolf

Odpowiedz

56

nie rozumiem dokładnie, co Twój kod próbuje zrobić, ale można zrobić zmienne dostępne w żadnym obsługa zdarzeń korzystająca z zalet funkcji zamknięcia:

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

W zależności od dokładnego kodu Możesz zawsze zrobić coś takiego, aby zachować dostęp do zmiennych dla ciebie.

Od swoimi uwagami, jeśli to, co starasz się osiągnąć to:

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

Następnie, można zrobić to z własnej wykonywania funkcji (Iife), który przechwytuje argumenty, które mają w zamknięciu jako to wykonuje i zwraca rzeczywistą funkcję obsługi zdarzenia:

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

Aby uzyskać więcej informacji na temat jak działa Iife, zobacz także inne nazwy:

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?

Ta ostatnia wersja jest chyba łatwiej zobaczyć, co robi tak:

// 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])); 

Możliwe jest również użycie .bind() dodać argumenty wywołanie zwrotne. Wszelkie argumenty przekazywane do .bind() będą poprzedzone argumentami, które będzie miało samo wywołanie zwrotne. Tak, można to zrobić:

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

tak, prawie to, co próbuję zrobić, ale co, jeśli funkcja anonimowa zostanie przekazana jako parametr przez addClickHandler i chcesz nadać tej funkcji niektóre parametry z wydarzeniem takim jak: element.addEventListener ("kliknięcie", func (zdarzenie , this.elements [i])); – sebas2day

+2

@ sebas2day - Nie można wykonać elementu 'element.addEventListener ('kliknij', func (event, this.elements [i]))'. JavaScript po prostu nie działa w ten sposób. Są na to inne sposoby, używając zamknięć, ale nie możesz tego zrobić tak, jak napisałeś. addEventListener wywołuje wywołanie zwrotne z dokładnie jednym argumentem (zdarzeniem) i nie można tego zmienić w żaden sposób. – jfriend00

+0

Dodałem kolejny przykład wykonania tego do końca mojej odpowiedzi. – jfriend00

0

this wewnątrz doThings jest przedmiotem okno.Zamiast tego spróbuj tego:

6

Coś, czego możesz spróbować używa metody wiązania, myślę, że to osiąga to, o co prosiłeś. Jeśli nic innego, to nadal jest bardzo przydatne.

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

Z uwagi na aktualizację pierwotnego pytania wygląda na to, że występują problemy z kontekstem ("ten") podczas przekazywania procedur obsługi zdarzeń. Podstawy są wyjaśnione na przykład tutaj http://www.w3schools.com/js/js_function_invocation.asp

Prosta wersja robocza swojej przykład można odczytać

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

Zobacz także Javascript call() & apply() vs bind()?

-1
let obj = MyObject(); 

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

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

Jak to rozwiązuje problem PO? – RamenChef

+0

Parametr param może być również funkcją zwrotną (w kontekście globalnym), a więc można go łatwo wywołać, zgodnie z żądanymi parametrami. –

1

To jest stare pytanie, ale jeden wspólny. Więc pozwól mi dodać ten tutaj.

ze składnią ES2015 można go osiągnąć bardziej zwięzły sposób:

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

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