2010-09-02 13 views
28

Tengo una página que tiene algún javascript que necesita ejecutarse en la carga de la página. Dicho javascript necesita localizar el componente del lado del cliente de un ServerControl, que lo hace con $ find().

Por supuesto, si emito mi código directamente en la página, se ejecuta cuando la página se está leyendo, y falla porque nada de lo que depende está aún inicializado.

Si pongo mi código dentro de la función pageLoad(), funciona bien, porque asp.net conecta automáticamente un controlador de carga para cualquier función llamada pageLoad(). El problema es que realmente no me gusta la solución pageLoad(), principalmente porque es un único nombre global. Si ingreso algún código usando pageLoad(), simplemente sé que algún otro programador va a copiar el enfoque, en algún lugar inapropiado, y vamos a terminar con una página que incluye dos o más funciones diferentes de pageLoad(), y el resultado será un montón de misteriosos errores que llevará una eternidad rastrear.

Así que puse mi código dentro de una función anónima pasada a jquery's $ (document) .ready(). Esto falla, porque se ejecuta antes de que exista el componente del lado del cliente de ServerControl.

Así que puse mi código dentro de una función anónima pasada por Sys.Application.add_load(). Esto también falla, porque Sys no está definido.

Así que finalmente me fijo en poner mi código dentro de Sys.Application.add_load(), y luego ponerlo dentro de una función llamada por $ (document) .ready(). Esto funciona, pero produce casi tanta acidez estomacal como pageLoad().

<script type="text/javascript"> 
    $(document).ready(function(){ 
     Sys.Application.add_load(function(){ 
      var component = $find(<clientid>); 
      if (component) { <do something> } 
     }); 
    }); 
</script> 

Tiene que haber una forma mejor de manejar esto.

¿Alguna idea?

Respuesta

20

Si usted tiene control sobre el código subyacente, puede registrar el JavaScript para funcionar en el arranque a través de algo como:

this.Page.ClientScript.RegisterStartupScript(
    this.GetType(), 
    "StartupScript", 
    "Sys.Application.add_load(function() { functioncall(); });", 
    true); 

Mientras que su componente se ha cargado a través de Sys.Application.add_init() debería estar bien ...

+0

Eso parece funcionar para nosotros. –

3

creo que si se agrega (o mover) un control ScriptManager por encima de su bloque de script, no habría necesidad de envolverlo en función de jQuery $(document).ready(). Al hacer esto, al parecer Sys estará disponible como el ScriptManager:

inyecta la mayor parte de esa JavaScript en la ubicación exacta que el control ScriptManager se coloca en en la página. [http://encosia.com/2007/08/16/updated-your-webconfig-but-sys-is-still-undefined/]

Sin embargo, esta solución todavía puede dar ardor de estómago ya que sin duda no sería obvio para cualquier desarrollador desprevenido lo que el ScriptManager es en realidad proporcionando aquí.

Otro método donde las referencias de scripts se agregan dentro del ScriptManager (ver "Mejor forma" discutido en el artículo vinculado arriba) tampoco me sienta bien ya que no soy un gran admirador del enfoque completo de ScriptManager.

5

Me gustaría ofrecer una alternativa para aquellos que están tratando de construir bibliotecas externas y tratando de seguir la mentalidad discreta de javascript tanto como sea posible dentro de .NET.

pageLoad es un excelente método para conectar automáticamente los eventos AJAX que debe disparar en cada carga de la página (ya sea que la carga proviene de un botón de navegación de vuelta a esta página, un botón de navegación hacia adelante a la página, una devolución de llamada AJAX, una norma carga de página, etc.), y ya que no tiene que preocuparse de esperar que el ScriptManager exista en el DOM, y su nombre tiene sentido, en su mayor parte (pageLoad vs. body.onload está ligeramente confuso para los codificadores que no son .NET, pero para una persona .NET, tiene sentido que pageLoad desencadene CADA página cargada, incluso después de devoluciones de llamadas, ya que el comportamiento es idéntico para el lado del servidor Page_Load). Una vez dicho esto, sus preocupaciones son buenas: no desea dos instancias de pageLoad en una página determinada, ya que se romperá. Aquí hay una solución directa de JavaScript que es segura para todos sus desarrolladores, permite el uso de pageLoad, no se preocupa por el DOM existente, no garantiza que haya colisiones de código y funciona maravillosamente para nosotros.

En su biblioteca principal javascript, defina pageLoad, así como una función de ayuda:

if (!pageLoad) { var pageLoad = function (sender, args) {}; }; 
if (!mylibrarynamespace) {var mylibrarynamespace = {};}; 
if (!mylibrarynamespace.registerStartupScript) mylibrarynamespace.registerStartupScript = function (fn) { 
    /* create local pointer for added function */ 
    var f = fn; 

    /* create pointer to existing pageLoad function */ 
    var pLoad = pageLoad; 

    /* add new function pointer to pageLoad by creating new anonymous function (search Google for "javascript enclosures" for why pl and f will persist with this newly defined anonymous function) */ 
    pageLoad = function (sender, args) { 
    pLoad(sender,args); 
    f(sender, args); 
    } 
} 

Luego, para utilizarlo en cualquier lugar en el código del lado del cliente, simplemente haga lo siguiente:

mylibrarynamespace.registerStartupScript(
    function (sender, args){ 
     /* do my AJAX always enabled startup code logic here*/ 
    } 
); 

Para facilitar el cambio de la funcionalidad, recomiendo que la función anónima aprobada llame a una función dentro de esa página o subconjunto de control de su biblioteca para que solo tenga que cambiar la declaración de función de la biblioteca (en el archivo o en tiempo de ejecución dinámicamente) cambiar cómo la pag eLoad para esa parte particular de su sitio funciona.

+0

Es más idóneo en javascript escribir sus primeras líneas como esta: var pageload = pageload || función (emisor, argumentos) {}; – Goyuix

0

Pruebe utilizar el ScriptManager para registrar el bloque de script del cliente, pero proporcione un título único para cada llamada de función adicional, especialmente si tiene parámetros únicos si está utilizando la misma función pero con diferentes valores de parámetro. Si usa la técnica add_load, solo se debe usar cuando la carga de la página no es una publicación posterior, es decir, solo se llama una vez después de una actualización de página o carga de página sin una publicación posterior.

intente esto en su lugar: ScriptManager.RegisterClientScriptBlock (esto, GetType(), "título único", "alerta ('prueba rápida');", verdadero);

Cuestiones relacionadas