2010-07-10 10 views
72

Supongamos que adjuntamos un controlador .click() a una etiqueta de anclaje (<a>) en la devolución de llamada $(document).ready. Este controlador cancelará la acción predeterminada (siguiendo el href) y mostrará una alerta.

Lo que me gustaría saber es cuándo se ejecutará exactamente la devolución de llamada y si es posible que el usuario haga clic en el delimitador (el documento se ha mostrado en el navegador) pero el evento aún no se ha conectado.

Aquí hay diferentes páginas HTML que contienen un delimitador pero el orden de inclusión de las secuencias de comandos es diferente. ¿Cuál es la diferencia (si hay alguna) entre ellos? ¿Los diferentes navegadores se comportarán de manera diferente?

Página1:

<html> 
<head> 
    <title>Test 1</title> 
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script> 
    <script type="text/javascript"> 
    $(function() { 
     $('a').click(function() { 
      alert('overriding the default action'); 
      return false; 
     }); 
    }); 
    </script> 
</head> 
<body> 
    <a href="http://www.google.com">Test</a> 
</body> 
</html> 

Página2:

<html> 
<head> 
    <title>Test 1</title> 
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script> 
</head> 
<body> 
    <a href="http://www.google.com">Test</a> 
    <script type="text/javascript"> 
    $(function() { 
     $('a').click(function() { 
      alert('overriding the default action'); 
      return false; 
     }); 
    }); 
    </script> 
</body> 
</html> 

Page3:

<html> 
<head> 
    <title>Test 1</title> 
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
</head> 
<body> 
    <a href="http://www.google.com">Test</a> 
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script> 
    <script type="text/javascript"> 
    $(function() { 
     $('a').click(function() { 
      alert('overriding the default action'); 
      return false; 
     }); 
    }); 
    </script> 
</body> 
</html> 

Entonces, ¿es posible que un usuario se le redirecciona a la href haciendo clic en el anclaje y nunca ve la alerta (ignorando el caso de Javascript desactivado, por supuesto)? ¿Podría suceder esto en cualquiera de los ejemplos que proporcioné?

Todo lo que necesito es asegurarme de que el controlador de eventos click se haya adjuntado al ancla antes de que el usuario tenga la posibilidad de hacer clic en este ancla. Sé que puedo proporcionar un href vacío y luego mejorarlo progresivamente en javascript, pero esta es una pregunta más general.

¿Qué sucederá en caso de que el HTML sea generado rápidamente por el servidor web, pero la biblioteca jquery tarda tiempo en ser extraída de un servidor distante? ¿Esto influenciará mi escenario? ¿Cuál es el orden de inclusión de los scripts en comparación con la carga del DOM? ¿Podrían hacerse en paralelo?

Respuesta

59

El ejemplo 3 tendrá la posibilidad más alta de que el usuario pueda hacer clic en el enlace sin que el manejador se haya conectado todavía.Dado que va a cargar la biblioteca jQuery después el enlace se hace, si los servidores de Google son un poco lento (o la búsqueda de DNS tarda un segundo o algo así), o el ordenador del usuario es lento para procesar jQuery, el enlace no tendrá su haga clic en controlador asociado cuando el usuario intente hacer clic en él.

Otra situación en la que esto podría suceder es si usted tiene una página muy grande o lenta la carga y este enlace es en la parte superior. Entonces el DOM puede no estar completamente listo cuando partes de él son visibles. Si está ejecutando en un problema como este, lo más seguro que hacer es:

  1. carga jQuery en el head (ejemplo 1 ó 2)
  2. Una el evento click inmediatamente después del elemento <a>, pero no en una devolución de llamada DOMReady. De esta forma se llamará de inmediato y no esperará el resto del documento.

Una vez que se procesa un elemento, que puede ser descargado desde el DOM, y posteriormente jQuery puede acceder a ella:

<a href="http://www.google.com">Test</a> 
<script type="text/javascript> 
    // No (document).ready is needed. The element is availible 
    $('a').click(function() { 
     alert('overriding the default action'); 
     return false; 
    }); 
</script> 

Además, edificio en el comentario de user384915, si la acción es totalmente dependiente JavaScript, entonces ni siquiera la hacen como parte del HTML, añadir después de jQuery está listo:

<script type="text/javascript"> 
jQuery(function($){ 
    $("<a />", { 
     style: "cursor: pointer", 
     click: function() { 
     alert('overriding the default action'); 
     return false; 
     }, 
     text: "Test" 
    }).prependTo("body"); 
}); 
</script> 
15

usted tiene un par de preguntas diferentes aquí

¿Cuándo exactamente se ejecuta el $ (document) ready devolución de llamada?

Se ejecuta tan pronto como el DOM esté completamente cargado. NO cuando todo (como imágenes) termina de descargarse como lo haría .load(). Es (en general) antes de eso, básicamente es cuando la página se construye.

Lo que me gustaría saber es cuándo exactamente la devolución de llamada se ejecutará

Cuando se hace clic.

es posible que el usuario haga clic en el anclaje (el documento ha sido se muestra en el navegador) pero el evento no se ha fijado todavía.

Sí, es posible. Pero ponerlo en .ready() te da la mejor posibilidad de que no lo haga.Solo hay 2 formas de hacerlo para estar "más seguro" de que no será así. En realidad, están usando el 'onclick' en el enlace en sí mismo, y colocando el javascript directamente después del enlace (y no en .ready()) para que se ejecute inmediatamente después de que se cree el enlace.

Además, no hay diferencia entre cómo funcionarán las 2 muestras de código que proporcionó. Sin embargo, en el segundo no necesita poner el código en .ready(), porque existe después del enlace, siempre se ejecutará después de que se haya creado el enlace. Si lo quitó de .ready() sería la primera de las 2 formas que describí anteriormente.

Además, en lugar de poner 'return false;' en su devolución de llamada, es mejor usar .preventDefault() y .stopPropagation() esto le permitirá especificar si desea evitar la acción predeterminada o evitar que el evento burbujee, o ambos.

+0

Así que está diciendo que la única manera de lograr lo que estoy buscando (tener la garantía de que el usuario ve una alerta antes de redirigir) es para cualquiera que use 'onclick' o adjuntar el' manejador click' justo después del enlace (no usando '$ (document) .ready')? –

+0

los ejemplos son diferentes dependiendo de si tiene activado el almacenamiento en búfer de salida o si utiliza codificación fragmentada. – galambalazs

+0

¿Cuál de los tres ejemplos sería el mejor en términos de mi objetivo asumiendo que el almacenamiento en memoria está habilitado? ¿Qué hay de la codificación fragmentada? –

2

Depende de muchas cosas. Si ha fragmentado la codificación, por ejemplo, es posible que un usuario obtenga un fragmento, pero como el documento aún no está listo, el oyente no se adjuntará.

El evento listo jQuery es la DOMContentLoaded evento en los navegadores compatibles con el W3C (normalizada en la especificación HTML 5), y algunas alternativas de este en otros (como readystate en IE).

DOMContentLoaded (MDC)

Cocida a la página del objeto de documento al analizar el documento es terminado. Cuando se activa este evento , el DOM de la página está listo.

Dado que esto ocurre antes de la representación, sería una suposición sólida que una devolución de llamada ejecutada después de este evento pueda evitar la interacción del usuario en una página no lista.

Pero como señaló Peter Michaux en his article debido a las diferencias de cómo los navegadores implementan este evento "una técnica robusta para la activación temprana no es posible en los cuatro navegadores principales".

Así que yo diría que no se puede confiar 100% en el caso listo jQuery, pero la mayor parte del tiempo que va a trabajar bien.

0

De seguro es posible "engañar" la advertencia de alerta (incluso si el Javascript está habilitado). Intenta arrastrar el enlace en el campo url y verás que se ejecutará sin esa advertencia. Esto es especialmente problemático si el enlace desencadena la acción de eliminación.

Sobre la devolución de llamada de document.ready - También tengo ese problema. Dejame explicar. Estamos haciendo un proyecto donde todos los formularios se muestran en ventanas emergentes (ventana de jQuery). Entonces, cuando la ventana emergente está cerrada (por ahora), la página se vuelve a cargar y tuve casos en los que me redireccionaron a otra pantalla en lugar de abrir una nueva ventana emergente.

Totalmente de acuerdo con user384915 sobre poner javascript directamente en el evento onClick o incluso mejor a la etiqueta href.

1

Su tercer ejemplo proporciona la mayor probabilidad de que el usuario haga clic rey sin el controlador de anulación que se ha adjuntado. El navegador generalmente descarga y analiza cada <script> antes de pasar al siguiente. Estás extrayendo jQuery de una fuente externa (Google), que, si bien es confiable, podría no estar disponible o demorarse en cargarse. Tienes que ambos bloques <script> al final de su documento <body>, por lo que las zonas anteriores de la página probable que ya se han descargado y entregado a la pantalla, mientras que estos dos últimos guiones se manejan. Si bien este enfoque se recomienda para presentar una experiencia de carga de página receptiva para el usuario, podrían hacer clic durante este período incierto, y por supuesto, el controlador de reemplazo aún no habría sido adjuntado.

Hay un artículo interesante sobre YUIblog guiones y orden de carga here.

Cuestiones relacionadas