web-dev-qa-db-fra.com

Différence entre RegisterStartupScript et RegisterClientScriptBlock?

La seule différence entre RegisterStartupScript et RegisterClientScriptBlock est que RegisterStartupScript met le javascript avant le </form> balise de la page et RegisterClientScriptBlock la met juste après le début de <form> tag de la page?

Aussi, quand choisiriez-vous l'un par rapport à l'autre? J'ai rédigé un exemple rapide de page où j'avais un problème et je ne suis pas sûr de la raison exacte pour laquelle cela se produit.

Voici le balisage 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>

Voici le code derrière:

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

Le problème est que lorsque je clique sur le bouton btnPostBack, il effectue une publication et modifie le libellé en rouge, mais lorsque je clique sur le bouton btnPostBack2, une publication est postée, mais la couleur de l'étiquette ne devient pas rouge. Pourquoi est-ce? Est-ce parce que l'étiquette n'est pas initialisée?

J'ai aussi lu que si vous utilisez un UpdatePanel, vous devez utiliser ScriptManager.RegisterStartupScript, mais si j’ai un MasterPage, utiliserais-je ScriptManagerProxy?

134
Xaisoft

Voici un ancien fil de discussion où j'ai énuméré les principales différences et les conditions d'utilisation de chacune de ces méthodes. Je pense que vous trouverez peut-être utile de parcourir la discussion.

Pour expliquer les différences en rapport avec votre exemple posté:

une. Lorsque vous utilisez RegisterStartupScript, le script sera rendu après tous les éléments de la page (juste avant la balise de fin du formulaire). Cela permet au script d'appeler ou de référencer des éléments de page sans qu'il soit possible de ne pas les trouver dans le DOM de la page.

Voici la source rendue de la page lorsque vous appelez la méthode RegisterStartupScript:

<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. Lorsque vous utilisez RegisterClientScriptBlock, le script est rendu juste après la balise Viewstate, mais avant les éléments de la page. Puisqu'il s'agit d'un script direct (et non d'une fonction pouvant être appelée, il sera immédiatement exécuté par le navigateur. Mais le navigateur ne trouve pas l'étiquette dans le DOM de la page à ce stade et vous devriez donc recevoir une erreur "Objet non trouvé".

Voici la source rendue de la page lorsque vous appelez la méthode RegisterClientScriptBlock:

<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';

Par conséquent, pour résumer, vous devez appeler cette dernière méthode si vous souhaitez rendre une définition de fonction. Vous pouvez ensuite rendre l'appel à cette fonction en utilisant l'ancienne méthode (ou ajouter un attribut côté client).

Modifier après les commentaires:


Par exemple, la fonction suivante fonctionnerait:

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

Voici un exemple le plus simple de la communauté ASP.NET, qui m'a permis de bien comprendre le concept ....

quelle différence cela fait-il?

Voici un moyen de mettre en évidence une zone de texte sur une page lorsque celle-ci est chargée dans le navigateur, par exemple avec Visual Basic à l'aide de la méthode RegisterStartupScript:

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

Cela fonctionne bien car la zone de texte de la page est générée et placée sur la page au moment où le navigateur accède au bas de la page et accède à ce petit peu de JavaScript.

Mais si au lieu de cela, il était écrit comme ceci (en utilisant la méthode RegisterClientScriptBlock):

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

La focus ne se rendra pas au contrôle de la zone de texte et une erreur JavaScript sera générée sur la page.

La raison en est que le navigateur rencontre le JavaScript avant que la zone de texte ne se trouve sur la page. Par conséquent, le JavaScript ne pourra pas trouver un TextBox1.

6
c-sharp user