2011-07-15 14 views
5

Deseo desencadenar un evento cuando mi mouse ingresa un div y un evento por separado cuando abandona el div usando jQuery. Sé que hay muchos complementos, muestras de código, etc. que resuelven este problema en particular. Solo tengo curiosidad de qué manera sería la más eficiente en términos de rendimiento y administración de la memoria.Comparación de métodos para vincular evento mouseleave junto con un evento mouseenter en jQuery

Así, por ejemplo, supongamos que tenemos el código HTML siguiente manera:

<div class="mouse-trap"> 1 </div> 
<div class="mouse-trap"> 2 </div> 
... 
<div class="mouse-trap"> n-1 </div> 
<div class="mouse-trap"> n </div> 

1. competiciones separadas

Podemos mantener los eventos por separado. Este código es legible y fácil de usar.

$(".mouse-trap").bind('mouseenter', function() { 
    // mouse came in 
}); 

$(".mouse-trap").bind('mouseleave', function() { 
    // mouse left 
}); 

2. eventos anidados

En lugar de mantener siempre un acontecimiento "mouseleave" alrededor, sólo crean cuando es necesario, y luego tirarlo a la basura cuando hayamos terminado, ya que no siempre será solamente un evento mouseleave para cada evento de mouseenter.

$(".mouse-trap").bind('mouseenter', function() { 
    // mouse came in 

    $(this).one('mouseleave', function() { 
     // mouse left 
    }); 
}); 

En el primer escenario si tiene n eventos, esto significa jQuery es constantemente tienen que escuchar n x 2 eventos.

En el segundo escenario, asumiendo las div de no están anidados uno dentro del otro, que sólo está escuchando n + 1 eventos en cualquier punto dado.

Es cierto que no estoy seguro de exactamente cuánto tiempo involucra la búsqueda de eventos, pero sospecho que de navegador a navegador, y de computadora a computadora, sería diferente. Para un valor relativamente pequeño de n esto probablemente nunca sea un problema. ¿Pero qué pasa si n es realmente grande? ¿Habría una diferencia notable?


Ahora, ¿cómo cambian las cosas si puede tener divs anidados uno dentro del otro?

Por ejemplo:

<div class="mouse-trap"> 
    <div class="mouse-trap"> 
     <div class="mouse-trap"> 
     ... 
     </div> 
     <div class="mouse-trap"> 
     ... 
     </div> 
    </div> 
    ... 
    <div class="mouse-trap"> 
     ... 
    </div> 
</div> 

El peor de los casos aquí sería n divs anidados unos dentro de otros.

Como están anidados, creo que el evento "mouseleave" no se invocará en los divs externos a medida que se mueve hacia adentro. En este caso, creo que los dos escenarios tendrían que hacer un seguimiento de los eventos n x 2, pero solo al pasar el mouse sobre el div más interno.


Ahora esto plantea otra cuestión de cuánto sobrecarga se requiere para vincular y desvincular eventos. Creí haber leído hace un tiempo que jQuery mantiene todos los eventos en cola, aunque no pude encontrar documentación específica que confirmara esto al investigar este tema. Así que dependiendo de la estructura de datos utilizada, la puesta en cola/desencola probablemente tiene ya sea un O (1) o O (n) costo. ¿Alguien sabe los detalles de esto?

En el escenario 1, enlaza todo una vez por adelantado y ya no tiene que meterse con él (salvo que las nuevas trampas div.mouse se agreguen dinámicamente a la página). Eso es n x 2 enlaces que tienen lugar.

En el escenario 2, sólo enlaza n eventos en la delantera, pero podría ser teóricamente no hay límite al número de veces que entrar y salir de un área con el ratón. Esto crea una posibilidad de enlaces infinitos necesarios. Pero en el mismo aspecto, un mouse (y el humano que opera ese mouse) solo pueden moverse tan rápido, por lo que estas vinculaciones también se extienden por un período de tiempo mayor. Esto podría minimizar el efecto de las numerosas ataduras.


Todo eso para decir, creo que el segundo escenario es probablemente mejor, pero ¿estoy pasando por alto algo más? ¿Hay otras maneras de hacerlo que sean mejores que las dos que enumeré?

Pido disculpas por la extensión de esta publicación. Solo quería asegurarme de haber profundizado en mi proceso de pensamiento actual. Estoy trabajando en algo que tendrá una gran cantidad de eventos de mouse y quiero asegurarme de jugar bien con los sistemas de las personas.

+1

Hay una consideración muy importante que falta aquí - el [alcance incluido en los cierres que estés de unión puede tener un gran impacto memoria] (http: // Google- styleguide.googlecode.com/svn/trunk/javascriptguide.xml?showone=Closures#Closures). –

+2

¿Ha considerado usar "mouseover" y "mouseout" en lugar de su problema de anidación? Con eso, si ingresas un elemento anidado, se desencadenará 'mouseout' en el elemento primario. –

+0

@Timothy Debo admitir que estaba un poco confundido por esa documentación. ¿Cómo afectaría eso a cada uno de los escenarios que especifiqué anteriormente? @leandre_b Eso es un buen punto. No estoy seguro de por qué no estaba pensando en eso. Eso definitivamente ayudará. –

Respuesta

3

Envuelva todo .mouse-trap en div, vincule los eventos solo una vez y use event.target para manejarlo.


Como nota al margen - deberías perfil y ver qué solución es la mejor para usted .

+0

+1, tan simple ... –

0

puede ser mejor como esto:

jQuery.fn.mouse_trap=function(f1,f2) 
{ 
var obj=$(this); 
obj.one('mouseenter',function(){enter(obj)}); 
function enter(obj) { 
    f1(obj); 
    obj.one('mouseleave',function(){leave(obj)}) 
} 
function leave(obj) { 
    f2(obj); 
    obj.one('mouseenter',function(){enter(obj)}) 
}} 

$(".mouse-trap").mouse_trap(function() { 
    // mouse came in 
},function() { 
    // mouse came out 
}); 

por lo jQuery va a escuchar solamente n eventos puede ser que podemos crear plug-in para N, donde N es el número de árboles anidados, pero tendrá que mantener los datos de todos elementos en algún lugar que harán que los eventos sean más lentos

+0

¿Sería esto realmente mejor si ya hubiera ingresado y dejado cada trampa para ratones al menos una vez? Al salir, cada mouse-trap tendría otro mouseenter vinculante. Si pasa el mouse y sale un montón de veces rápidamente, tendría que hacer muchas más ataduras para manejar. –

0

Aunque realmente no tengo todo el conocimiento sobre el peaje que esas dos soluciones tomarían en la ejecución del proyecto, me inclinaría personalmente hacia la primera avenida, separar los eventos.

Y acerca de algunas de sus preocupaciones:

  • Como dijo Timothy Jones en un comentario, usted tiene que considerar the scope included in the closures you're binding can have a great memory impact. Como dice el artículo, utilizar los argumentos de una función dentro de una devolución de llamada puede ocasionar problemas de rendimiento (que hasta ahora no conocía, es bueno saberlo). Aunque no lo estás haciendo exactamente en tu enfoque, la forma en que unes tus eventos no está muy lejos y podrías caer en la trampa a medida que avanzas en tu desarrollo. Al tener sus dos eventos separados, ni siquiera tendrá que preocuparse por eso.

  • En el escenario de elementos anidados, como sugerí en mi comentario, podría optar por un enfoque mouseover y mouseout.Debería ocuparse de 'ingresando al hijo mientras todavía está en el padre', ya que al ingresar un hijo con mouseover se activará mouseout en el elemento primario.

  • Por último, sobre el número de oyentes activos binded, como eicto sugirió, desatar la corriente y luego ligar el caso opuesto como se les llama debería, en teoría, reducir el número de eventos totales unidas a la mitad.

Como ya he dicho, esto no es una respuesta técnica, sino por haber desarrollado algo similar, me encontré con esta avenida (eventos por separado) para ser el más adecuado tanto para la flexibilidad y la claridad en la final.

0

¿Qué hay de O (2) solución como esta:

HTML:

<div class="mouse-trap-container"> 
    <div class="mouse-trap"> 1 </div> 
    <div class="mouse-trap"> 2 </div> 
    ... 
    <div class="mouse-trap"> n-1 </div> 
    <div class="mouse-trap"> n </div> 
</div> 

JS:

$('div.mouse-trap-container') 
    .delegate('div.mouse-trap', 'mouseenter', function(e) { 
     // mouse came in 
}).delegate('div.mouse-trap', 'mouseleave', function(e) { 
    // mouse left 
}); 
-1

Tal vez esta no es la respuesta que estás buscando, pero ...
No se preocupe tanto por el rendimiento/gestión de la memoria ent - para las computadoras de hoy, este problema en particular es un problema tan trivial que ni siquiera vale la pena analizarlo a un nivel tan granular. Creo que es mucho más importante la limpieza y mantenimiento de su código. A fin de mantenerlo sencilla con una función hover():

$('.mouse-trap').hover(
    function() { 
    // mouse in 

    }, 
    function() { 
    // mouse out 
    } 
); 
+0

Empieza a ser un problema cuando se trata de IE <9 (y hasta cierto punto FF) – Mrchief

+0

No sé ... Siempre código para FF primero y luego pruebo en IE 7, 8, 9 y último Chrome y Safari. No he tenido ningún problema con este enfoque. – Kon

+0

¡El rendimiento es un problema cuando tienes muchos elementos a los que estás vinculando eventos, incluso hoy en día! – jor

Cuestiones relacionadas