ti-enxame.com

Sys.Application.add_load () vs. $ (document) .ready () vs. pageLoad ()

Eu tenho uma página que tem algum javascript que precisa ser executado no carregamento da página. O javascript precisa localizar o componente do lado do cliente de um ServerControl, o que ocorre com $ find ().

Obviamente, se eu emitir meu código diretamente na página, ele será executado à medida que a página estiver sendo lida e falhará porque nada do que depende ainda foi inicializado.

Se eu colocar meu código dentro de uma função pageLoad (), ele funcionará perfeitamente, porque o asp.net liga automaticamente um manipulador de onload para qualquer função chamada pageLoad (). O problema é que eu realmente não gosto da solução pageLoad () - principalmente porque é um único nome global. Se eu confirmar algum código usando pageLoad (), apenas sei que outro programador copiará a abordagem, em algum lugar inadequado, e terminaremos com uma página que inclui duas ou mais funções diferentes pageLoad () e o resultado será um monte de erros misteriosos que levarão uma eternidade para serem rastreados.

Então, eu coloquei meu código dentro de uma função anônima passada para $ (document) .ready () do jquery. Isso falha, porque é executado antes que o componente do lado do cliente do ServerControl exista.

Então, eu coloquei meu código dentro de uma função anônima passada por Sys.Application.add_load (). Isso também falha, porque o Sys é indefinido.

Por fim, decidi colocar meu código dentro de Sys.Application.add_load () e depois colocá-lo em uma função chamada por $ (document) .ready (). Isso funciona, mas dá quase tanta azia quanto pageLoad ().

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

Tem que haver uma maneira melhor de lidar com isso.

Alguma ideia?

30
Jeff Dege

Se você tiver controle sobre o code-behind, poderá registrar o JavaScript para executar na inicialização através de algo como:

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

Contanto que seu componente tenha sido carregado via Sys.Application.add_init (), você deve ficar bem ...

20
Heretic Monkey

Gostaria de oferecer uma alternativa para aqueles que estão tentando criar bibliotecas externas e seguem a mentalidade discreta de javascript, tanto quanto possível, no .NET.

o pageLoad é um excelente método para conectar automaticamente AJAX que devem ser disparados em cada carregamento da página (se esse carregamento é proveniente de uma navegação no botão voltar para esta página, uma navegação no botão avançar na página, AJAX, carregamento de página padrão etc.), e como você não precisa se preocupar em esperar que o ScriptManager exista no DOM, ele é nomeado de uma maneira que faz sentido , na maioria das vezes (pageLoad vs. body.onload é um pouco confuso para codificadores não .NET, mas para uma pessoa .NET, faz sentido que o pageLoad ative TODAS as carregamentos de páginas, inclusive após retornos de chamada, pois o comportamento é idêntico ao servidor Page_Load). Dito isso, suas preocupações são boas - você não deseja duas instâncias de pageLoad em uma determinada página, pois ela será quebrada. Aqui está uma solução javascript direta que é segura para todos os desenvolvedores, permite que o o uso do pageLoad, não se preocupa com o DOM existente, garante nenhuma colisão de código e funciona maravilhosamente para nós.

Na sua biblioteca javascript principal, defina pageLoad, bem como uma função auxiliar:

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);
    }
}

Em seguida, para usá-lo em qualquer lugar do código do lado do cliente, faça o seguinte:

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

Para facilitar a alteração da funcionalidade, recomendo que a função transmitida em anônimo chame uma função dentro desse subconjunto da página ou controle da sua biblioteca, para que você só precise alterar a declaração de função da sua biblioteca (no arquivo ou no tempo de execução dinamicamente) para alterar como o pageLoad para essa parte específica do seu site funciona.

5
Jonathan

Acredito que se você adicionar (ou mover) um controle ScriptManager acima do seu bloco de script, não precisará envolvê-lo na função $(document).ready() do jQuery. Ao fazer isso, aparentemente Sys estará disponível como o ScriptManager:

injeta a maior parte desse JavaScript no local exato em que o ScriptManager está posicionado na página. [ http://encosia.com/2007/08/16/updated-your-webconfig-but-sys-is-still-undefined/ ]

No entanto, essa solução ainda pode causar azia, pois certamente não seria óbvio para qualquer desenvolvedor desavisado o que o ScriptManager está realmente fornecendo aqui.

Outro método no qual as referências de script são adicionadas dentro do ScriptManager (consulte "Melhor maneira" discutida no artigo vinculado acima) também não me agrada muito, pois eu não sou um grande fã de toda a abordagem do ScriptManager.

3
Bermo

Tente usar o ScriptManager para registrar o bloco de scripts do cliente, mas forneça um título exclusivo para cada chamada de função adicional, especialmente se ele tiver parâmetros exclusivos, se você estiver usando a mesma função, mas com valores de parâmetros diferentes. Se você usar a técnica add_load, ela deverá ser usada apenas quando o carregamento da página não for uma postagem de retorno, ou seja, chamado apenas uma vez após a atualização da página ou o carregamento da página sem uma postagem de retorno.

tente isso: ScriptManager.RegisterClientScriptBlock (this, GetType (), "title exclusivo", "alert ('teste rápido');", true);

0
RetroCoder