Como posso passar argumentos para manipuladores de eventos em jQuery?

91

Com código jQuery como:

$("#myid").click(myfunction);

function myfunction(arg1, arg2) {/* something */}

Como faço para passar argumentos myfunctionao usar jQuery?

Edward Wong Hau Pepelu Tivrusk
fonte
Possível duplicata de Passar uma função com parâmetros como parâmetro?
Michał Perłakowski

Respostas:

110

A maneira mais simples é fazer assim (assumindo que você não deseja que nenhuma informação do evento seja passada para a função) ...

$("#myid").click(function() {
    myfunction(arg1, arg2);
});

jsFiddle .

Isso cria uma função anônima, que é chamada quando o clickevento é disparado. Isso, por sua vez, chamará myfunction()com os argumentos que você fornecer.

Se você deseja manter o ThisBinding(o valor de thisquando a função é chamada, defina como o elemento que disparou o evento), chame a função com call().

$("#myid").click(function() {
    myfunction.call(this, arg1, arg2);
});

jsFiddle .

Você não pode passar a referência diretamente da forma como seu exemplo afirma, ou seu único argumento será o objeto jQueryevent .

Se você não quiser passar a referência, você deve aproveitar do jQuery proxy()função (que é um wrapper cross browser para Function.prototype.bind()). Isso permite que você passe argumentos, que são vinculados antes do eventargumento.

$("#myid").click($.proxy(myfunction, null, arg1, arg2));   

jsFiddle .

Neste exemplo, myfunction()seria executado com seu ThisBindingintacto ( nullnão é um objeto, portanto, o thisvalor normal do elemento que acionou o evento é usado), junto com os argumentos (em ordem) e arg1, arg2finalmente, o eventobjeto jQuery , que você pode ignorar se não for necessário (nem mesmo nomeie nos argumentos da função).

Você também pode usar o eventobjeto jQuery datapara passar dados, mas isso exigiria modificação myfunction()para acessá-lo via event.data.arg1(que não são argumentos de função como sua pergunta menciona), ou pelo menos a introdução de uma função de proxy manual como o exemplo anterior ou gerado usando o último exemplo.

alex
fonte
2
tenha em mente, você perderá o contexto jquery $ (this) em myfunction (). Para manter, chame myfunction(this, arg1, arg2)do manipulador anônimo. Então sua função pode fazermyfunction(el, arg1, arg2) { alert($(el).val()); }
lambinator
11
@geosteve: Se você quiser mantê-lo, use myfunction.call(this, arg1, arg2).
alex de
1
Isso não é passar argumentos para a função, como a pergunta pede. Ele está chamando uma função que chama outra função. Aninhar funções dentro de funções anônimas não é uma boa ideia, pois você não pode desvincular a função anônima facilmente.
George Filippakos
1
@ geo1701 Você pode, se usar um namespace personalizado e se vincular apenas uma vez a ele. Para a maioria dos propósitos, está OK. Mas você perde aquele benefício que mencionou.
alex
1
Concordo com @ geo1701, tive que remover o manipulador de eventos e sua solução é apenas uma que funcionou.
Pavel K
76
$("#myid").on('click', {arg1: 'hello', arg2: 'bye'}, myfunction);

function myfunction(e) {

    var arg1 = e.data.arg1;
    var arg2 = e.data.arg2;

    alert(arg1);
    alert(arg2);

}

//call method directly:
myfunction({
    arg1: 'hello agian', 
    arg2: 'bye again'
});

Também permite vincular e desvincular manipuladores de eventos específicos usando os métodos on e off.

Exemplo:

$("#myid").off('click', myfunction);

Isso desvincularia o manipulador de myfunction de #myid

George Filippakos
fonte
Isso não é passar argumentos para a função, como a pergunta pede.
alex
4
É assim que você passa argumentos (você os envolve dentro de um objeto).
George Filippakos
É como você passa dados, mas é difícil chamá-los de argumentos de função.
alex
6
É a melhor solução para a resposta aceita, pois usa o padrão recomendado para ligar e desligar os ouvintes usando os métodos On / Off.
George Filippakos
7
Se você acha que a desvinculação é muito rara, você deve ter uma experiência muito limitada. Por favor, não diga contribuições de outras pessoas - esta é uma base de conhecimento coletiva, não uma competição. Não há respostas certas ou erradas.
George Filippakos
12

embora você certamente deva usar a resposta de Alex, o método "bind" da biblioteca de protótipos foi padronizado no Ecmascript 5 e logo será implementado em navegadores nativamente. Funciona assim:

jQuery("#myid").click(myfunction.bind(this, arg1, arg2));
Bretão
fonte
2
Será thisdefinido para um contexto diferente se você usar esse método, por exemplo, bind()fazê-lo thisnesse contexto (global) pode resultar no manipulador de cliques com o windowobjeto thisem vez de uma referência ao #myidelemento?
alex
2
@alex, você está certo. jQuery vinculará o elemento #myid a 'this' em seus manipuladores de eventos e, usando o método de vinculação, o substituirá. Escrevi este post há vários anos, parece que é difícil dizer o que eu estava pensando na época. Acho que presumo que as pessoas que estão lendo minhas respostas são inteligentes o suficiente para descobrir esses detalhes por si mesmas.
bretão,
12
Essa é uma suposição muito perigosa.
Travis
@Travis No momento da redação deste artigo (quase 11 anos após a resposta de Breton), caniuse.com relata que o Ecmascript 5 é compatível com 98,87% dos navegadores. (consulte caniuse.com/#search=ECMAScript%205 )
Stephan
@Stephan Meu comentário irônico foi direcionado a @Breton por supor people reading my answers are smart enough to figure these details out themselves, não sobre Ecmascript.
Travis
6

Tópico antigo, mas para fins de pesquisa; experimentar:

$(selector).on('mouseover',...);

... e verifique o parâmetro "data": http://api.jquery.com/on/

por exemplo:

function greet( event ) {
  alert( "Hello " + event.data.name );
}
$( "button" ).on( "click", {name: "Karl"}, greet );
$( "button" ).on( "click", {name: "Addy"}, greet );
dhc
fonte
4

Já existem ótimas respostas, mas de qualquer maneira, aqui estão meus dois centavos. Você também pode usar:

$("#myid").click({arg1: "foo", arg2: "bar"}, myfunction)

E o ouvinte ficaria assim:

function myfunction(event){ alert(event.data.arg1); alert(event.data.arg2); }

Leo
fonte
2

Simples:

$(element).on("click", ["Jesikka"],  myHandler);

function myHandler(event){
   alert(event.data);     //passed in "event.data"
}
T.Todua
fonte