Diferença entre RegisterStartupScript e RegisterClientScriptBlock?


139

É a única diferença entre a RegisterStartupScripteo RegisterClientScriptBlocké que RegisterStartupScript coloca o javascript antes do fechamento </form>tag da página e coloca RegisterClientScriptBlock-lo logo após o início <form>tag da página?

Além disso, quando você escolheria um sobre o outro? Escrevi uma página de amostra rápida em que tive um problema e não sei ao certo o motivo exato do motivo.

Aqui está a marcação aspx:

<html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
            <div>
                <asp:Label ID="lblDisplayDate" runat="server"
                           Text="Label" /><br />
                <asp:Button ID="btnPostback" runat="server" 
                            Text="Register Startup Script"
                            onclick="btnPostback_Click" /><br />
                <asp:Button ID="btnPostBack2" runat="server" 
                            Text="Register"
                            onclick="btnPostBack2_Click" />
            </div>
        </form>
    </body>
</html>

Aqui está o código por trás:

protected void Page_Load(object sender, EventArgs e)
{
    lblDisplayDate.Text = DateTime.Now.ToString("T");
}

protected void btnPostback_Click(object sender, EventArgs e)
{
    System.Text.StringBuilder sb = new System.Text.StringBuilder();
    sb.Append(@"<script language='javascript'>");
    sb.Append(@"var lbl = document.getElementById('lblDisplayDate');");
    sb.Append(@"lbl.style.color='red';");
    sb.Append(@"</script>");

    if(!ClientScript.IsStartupScriptRegistered("JSScript"))
    {
        ClientScript.RegisterStartupScript(this.GetType(),"JSScript",
        sb.ToString());
    }
}

protected void btnPostBack2_Click(object sender, EventArgs e)
{
    System.Text.StringBuilder sb = new System.Text.StringBuilder();
    sb.Append(@"<script language='javascript'>");
    sb.Append(@"var lbl = document.getElementById('lblDisplayDate');");
    sb.Append(@"lbl.style.color='red';");
    sb.Append(@"</script>");

    if (!ClientScript.IsClientScriptBlockRegistered("JSScriptBlock"))
    {
        ClientScript.RegisterClientScriptBlock(this.GetType(), "JSScriptBlock",  
        sb.ToString());
    } 
 }

O problema é quando clico no btnPostBackbotão, ele faz uma postagem e altera o rótulo para vermelho, mas quando clico no btnPostBack2, ele faz uma postagem, mas a cor do rótulo não muda para vermelho. Por que é isso? É porque o rótulo não foi inicializado?

Também li que se você estiver usando um UpdatePanel, precisará usar ScriptManager.RegisterStartupScript, mas se eu tiver um MasterPage, eu usaria ScriptManagerProxy?

Respostas:


162

Aqui está um tópico de discussão antigo, onde listei as principais diferenças e as condições em que você deve usar cada um desses métodos. Eu acho que você pode achar útil passar pela discussão.

Para explicar as diferenças como relevantes para o seu exemplo publicado:

uma. Quando você usa RegisterStartupScript, ele renderiza seu script depois de todos os elementos da página (logo antes da tag final do formulário). Isso permite que o script chame ou faça referência a elementos da página sem a possibilidade de não encontrá-los no DOM da página.

Aqui está a fonte renderizada da página quando você chama o RegisterStartupScriptmétodo:

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1"><title></title></head>
<body>
    <form name="form1" method="post" action="StartupScript.aspx" id="form1">
        <div>
            <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="someViewstategibberish" />
        </div>
        <div> <span id="lblDisplayDate">Label</span>
            <br />
            <input type="submit" name="btnPostback" value="Register Startup Script" id="btnPostback" />
            <br />
            <input type="submit" name="btnPostBack2" value="Register" id="btnPostBack2" />
        </div>
        <div>
            <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="someViewstategibberish" />
        </div>
        <!-- Note this part -->
        <script language='javascript'>
            var lbl = document.getElementById('lblDisplayDate');
            lbl.style.color = 'red';
        </script>
    </form>
    <!-- Note this part -->
</body>
</html>

b. Quando você usa RegisterClientScriptBlock, o script é renderizado logo após a tag Viewstate, mas antes de qualquer elemento da página. Como esse é um script direto (não é uma função que pode ser chamada , ele será executado imediatamente pelo navegador. Mas o navegador não encontra o rótulo no DOM da página nesse estágio e, portanto, você deve receber um "Objeto não encontrado" erro.

Aqui está a fonte renderizada da página quando você chama o RegisterClientScriptBlockmétodo:

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1"><title></title></head>
<body>
    <form name="form1" method="post" action="StartupScript.aspx" id="form1">
        <div>
            <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="someViewstategibberish" />
        </div>
        <script language='javascript'>
            var lbl = document.getElementById('lblDisplayDate');
            // Error is thrown in the next line because lbl is null.
            lbl.style.color = 'green';

Portanto, para resumir, você deve chamar o último método se pretender renderizar uma definição de função. Você pode renderizar a chamada para essa função usando o método anterior (ou adicionar um atributo do lado do cliente).

Editar após os comentários:


Por exemplo, a seguinte função funcionaria:

protected void btnPostBack2_Click(object sender, EventArgs e) 
{ 
  System.Text.StringBuilder sb = new System.Text.StringBuilder(); 
  sb.Append("<script language='javascript'>function ChangeColor() {"); 
  sb.Append("var lbl = document.getElementById('lblDisplayDate');"); 
  sb.Append("lbl.style.color='green';"); 
  sb.Append("}</script>"); 

  //Render the function definition. 
  if (!ClientScript.IsClientScriptBlockRegistered("JSScriptBlock")) 
  {
    ClientScript.RegisterClientScriptBlock(this.GetType(), "JSScriptBlock", sb.ToString()); 
  }

  //Render the function invocation. 
  string funcCall = "<script language='javascript'>ChangeColor();</script>"; 

  if (!ClientScript.IsStartupScriptRegistered("JSScript"))
  { 
    ClientScript.RegisterStartupScript(this.GetType(), "JSScript", funcCall); 
  } 
} 

1
Você pode explicar um pouco mais sobre as funções embutidas.
Xaisoft 20/03/2009

2
Editando minha postagem para melhor ilustrá-la com seu exemplo.
Cerebrus

1
Na verdade, não recebo um erro, a hora é atualizada, mas a cor não muda. E a parte da minha pergunta em que eu pergunto se preciso usar o ScriptManagerProxy se já tenho um ScriptManager definido em uma página mestre?
Xaisoft 20/03/2009

1
Terminar a edição. Não tenho certeza sobre o erro com o ScriptManagerProxy. Eu acho que você deve avaliar se essa não é realmente uma pergunta separada. ;-) #
2100 Cerebrus

1
Ótimo! Obrigado até agora. Não estou recebendo um erro com o ScriptManagerProxy. Eu só sei que você só pode declarar uma instância do ScriptManager, por isso, se eu já tiver um ScriptManager definido em uma página mestre, por exemplo, eu assumiria que usaria o ScriptManagerProxy.
Xaisoft 20/03/09

6

Aqui está um exemplo mais simples da comunidade ASP.NET, isso me deu uma compreensão clara do conceito ....

Que diferença isso faz?

Para um exemplo disso, aqui está uma maneira de colocar o foco em uma caixa de texto em uma página quando a página é carregada no navegador - com o Visual Basic usando o RegisterStartupScriptmétodo:

Page.ClientScript.RegisterStartupScript(Me.GetType(), "Testing", _ 
"document.forms[0]['TextBox1'].focus();", True)

Isso funciona bem porque a caixa de texto na página é gerada e colocada na página no momento em que o navegador desce até a parte inferior da página e acessa esse pouco de JavaScript.

Mas, se em vez disso, foi escrito assim (usando o RegisterClientScriptBlockmétodo):

Page.ClientScript.RegisterClientScriptBlock(Me.GetType(), "Testing", _
"document.forms[0]['TextBox1'].focus();", True)

O foco não chegará ao controle da caixa de texto e um erro JavaScript será gerado na página

A razão para isso é que o navegador encontrará o JavaScript antes que a caixa de texto esteja na página. Portanto, o JavaScript não poderá encontrar um TextBox1.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.