2011-09-23 10 views
7

El mecanismo jQuery ".triggerHandler()", a diferencia de ".trigger()", solo opera en el primer elemento al que hace referencia el Objeto jQuery para el que se llama. En otras palabras,jQuery ".triggerHandler()" vs. ".trigger()" cuando se seleccionan múltiples elementos

$('.all-over-the-page').triggerHandler("readjust"); 

sólo se llamará al manejador de "reajustar" para el primer elemento con la clase "all-over-the-página", incluso si hay muchos elementos de la página con esa clase. El método ".trigger()", por otro lado, los afectaría a todos.

Me doy cuenta de que puedo usar ".each()" para evitar esto (o simplemente escribir mi propio sustituto que hace eso por mí), pero ¿hay alguna razón por la cual los dos son diferentes a este respecto? No tiene sentido para mí. (Entiendo por supuesto que es casi seguro que no se puede cambiar ahora.)

edición aclarar:

Es probable que sea más fácil de entender por qué estoy rascándome la cabeza sobre esto si proporciono un contexto en el estilo de código que en realidad tengo. Cuando configuro código para varias características de "widget" en una página, eso a menudo implica manejadores de eventos. Un buen ejemplo es una forma de algún tipo que tiene algunos campos cuya relevancia está controlada por una casilla de verificación, un botón de opción o un selector. Una instancia común de esto es la casilla "Dirección de envío" que aparece en un trillón de sitios de comercio electrónico: si la casilla de verificación está marcada, la dirección de envío está deshabilitada y se utiliza la dirección de facturación.

Considere que algunos otros códigos pueden, por sus propios motivos, que son totalmente independientes del widget de control de casilla de verificación, hacer cosas en el formulario que pueden incluir la actualización de la configuración de la casilla de verificación mediante programación. En ese caso, ese otro código de widgets puede querer usar "triggerHandler()" para indicarle a los widgets, "oye, he actualizado algunas cosas, por lo que es posible que desee volver a verificar el estado actual y ajustarlo si es necesario".

Por lo tanto, si ".triggerHandler()" operaría sobre todos los elementos seleccionados, podría usar:

$theForm.find('input, select, textarea').triggerHandler('change'); 

y todos esos manipuladores podía correr y hacer todo lo que necesitan. Como ya he dicho, es bastante fácil de escribir: "? ... ¿Hay alguna razón por la cual los dos son diferentes a este respecto"

$theForm.find('input, select, textarea').each(function() { 
    $(this).triggerHandler('change'); 
}); 
+0

+1 buena pregunta Pointy –

+0

No estoy seguro de qué está tratando de hacer específicamente aquí. ¿Puedes dar un poco más de contexto de lo que intentas resolver? –

+0

Actualizado con más material explicativo. – Pointy

Respuesta

11

Creo que la idea es que triggerHandler() está destinado a ser una manera de invocar la función que como un manejador como si se tratara de cualquier otra función.

Como tal, hicieron triggerHandler() de modo que la función solo se invoca una vez, devuelve el valor de retorno real de la función, y no afecta el DOM con burbujas o comportamientos predeterminados.

Por supuesto, la función puede romperse si cambian el valor this a algo que no sea un elemento DOM, por lo que solo utilizan el primer elemento coincidente.

Si solo quiere usar su función, entonces probablemente solo tenga una referencia e invoque directamente, o como argumento al .each().

$('.element').each(handler_func); 

... siempre y cuando no es necesario el objeto event.


EDIT: O si desea que los valores devueltos por la invocación, utilice .map() lugar:

var return_values = $('.element').map(handler_func); 

EDIT: Con respecto al ejemplo proporcionado en la pregunta actualizado , una buena solución puede ser aprovechar la capacidad de extraParameters del método trigger()[docs] que puede decirle al controlador preventDefault() y stopPropagation().

$('.elememts').bind('click', function(e, was_code_triggered) { 

    if(was_code_triggered) { 
     e.preventDefault(); 
     e.stopPropagation(); 
    } 
    // your code 
}); 


// ... 


$('.elememts').trigger('click', true); // pass "true" to let handler know 
             // it wasn't a DOM event 

De los .trigger() documentos:.

"Tenga en cuenta la diferencia entre los parámetros adicionales que estamos aquí de paso y el parámetro EVENTDATA al método .bind() Ambos son mecanismos para pasar información a una controlador de eventos, pero el argumento extraParameters a .trigger() permite que se determine la información en el momento en que se desencadena el evento, mientras que el argumento eventData a .bind() requiere la información ya se computa en el momento en que el controlador está vinculado ".

+0

Bueno, está bien, pero me parece extraño escribir controladores de eventos que esperan poder devolver un valor. Y estoy de acuerdo con no hacer los comportamientos predeterminados; eso es realmente problemático con "hacer clic" en las casillas de verificación (por ejemplo). – Pointy

+0

@Pointy: Sí, es extraño, a menos que tenga una función que sea útil como una función independiente, así como un controlador. Creo que ese caso sería raro. ¿Fue el burbujeo desactivado lo que buscabas después de usar 'triggerHandler'? EDITAR: Acabo de notar la actualización de su pregunta. Leyendo ... – user113716

+2

@Pointy: veo lo que buscas. Sí, si no quieres '.each()' (ya sea pasando una función directamente, o usando 'triggerHandler()' dentro), quizás quieras considerar usar la capacidad * extraParameters * de '.trigger()' para pase una bandera que le dirá al controlador que debe 'prevenirDefault()' y 'stopPropagation()'. – user113716

Cuestiones relacionadas