Différence entre RegisterStartupScript et RegisterClientScriptBlock?


139

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

De plus, quand choisiriez-vous l'un plutôt que l'autre? J'ai écrit une page d'exemple rapide où j'ai eu 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 btnPostBackbouton, il effectue une publication et change l'étiquette en rouge, mais lorsque je clique sur btnPostBack2, il effectue une publication, 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 l'utiliser ScriptManager.RegisterStartupScript, mais si j'en ai un MasterPage, est-ce que j'utiliserais ScriptManagerProxy?

Réponses:


162

Voici un ancien fil de discussion où j'ai répertorié les principales différences et les conditions dans lesquelles vous devez utiliser chacune de ces méthodes. Je pense que vous trouverez peut-être utile de poursuivre la discussion.

Pour expliquer les différences en fonction de votre exemple publié:

une. Lorsque vous utilisez RegisterStartupScript, il rendra votre script 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 qu'il ne les trouve pas dans le DOM de la page.

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

<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 tout élément de la page. Puisqu'il s'agit d'un script direct (pas une fonction qui peut ê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 un "Objet non trouvé" Erreur.

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

<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 avez l'intention de 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); 
  } 
} 

1
Pouvez-vous expliquer un peu plus les fonctions en ligne.
Xaisoft

2
Modifier mon message pour mieux l'illustrer par rapport à votre exemple.
Cerebrus

1
En fait, je n'obtiens pas d'erreur, l'heure se met à jour, mais la couleur ne change pas. Qu'en est-il de la partie de ma question où je demande si je dois utiliser ScriptManagerProxy si j'ai un ScriptManager déjà défini dans une page maître?
Xaisoft

1
Finis d'éditer. Je ne suis pas sûr de l'erreur avec ScriptManagerProxy. Je pense que vous devriez évaluer si ce n'est pas vraiment une question distincte. ;-)
Cerebrus

1
Génial! Merci jusqu'ici. Je n'obtiens pas d'erreur avec ScriptManagerProxy. Je sais juste que vous ne pouvez déclarer qu'une seule instance de ScriptManager, donc si j'ai déjà un ScriptManager défini dans une page maître par exemple, je suppose que j'utiliserais ScriptManagerProxy à la place.
Xaisoft

6

Voici un exemple le plus simple de la communauté ASP.NET, cela m'a donné une compréhension claire du concept ...

quelle différence cela fait-il?

Pour un exemple de ceci, voici un moyen de mettre le focus sur une zone de texte sur une page lorsque la page est chargée dans le navigateur, avec Visual Basic en utilisant la RegisterStartupScriptméthode:

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 descend au bas de la page et accède à ce petit morceau de JavaScript.

Mais, si à la place c'était écrit comme ça (en utilisant la RegisterClientScriptBlockméthode):

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

Le focus n'atteindra pas le contrôle de zone de texte et une erreur JavaScript sera générée sur la page

La raison en est que le navigateur rencontrera le JavaScript avant que la zone de texte n'apparaisse sur la page. Par conséquent, le JavaScript ne pourra pas trouver un TextBox1.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.