it-swarm.com.de

Unterschied zwischen RegisterStartupScript und RegisterClientScriptBlock?

Ist der einzige Unterschied zwischen dem RegisterStartupScript und dem RegisterClientScriptBlock, dass RegisterStartupScript das Javascript vor dem schließenden </form> - Tag der Seite und RegisterClientScriptBlock direkt nach dem startenden <form> Tag der Seite?

Und wann würden Sie eine der anderen vorziehen? Ich habe eine kurze Beispielseite geschrieben, auf der ich ein Problem hatte, und ich bin mir nicht sicher, warum es passiert.

Hier ist das Aspx-Markup:

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

Hier ist der Code dahinter:

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

Das Problem ist, wenn ich auf die Schaltfläche btnPostBack klicke, ein Postback ausgeführt wird und die Beschriftung in Rot geändert wird. Wenn ich auf btnPostBack2 Klicke, wird ein Postback ausgeführt, die Beschriftungsfarbe ändert sich jedoch nicht zu rot. Warum ist das? Liegt es daran, dass das Etikett nicht initialisiert ist?

Ich habe auch gelesen, dass Sie, wenn Sie ein UpdatePanel verwenden, ScriptManager.RegisterStartupScript Verwenden müssen, aber wenn ich ein MasterPage habe, würde ich ScriptManagerProxy verwenden?

134
Xaisoft

Hier ist ein alter Diskussionsthread Hier habe ich die Hauptunterschiede und die Bedingungen aufgelistet, unter denen Sie jede dieser Methoden anwenden sollten. Ich denke, Sie finden es vielleicht nützlich, die Diskussion durchzugehen.

So erläutern Sie die Unterschiede, die für Ihr veröffentlichtes Beispiel relevant sind:

ein. Wenn Sie RegisterStartupScript verwenden, wird Ihr Skript nach allen Elementen auf der Seite (direkt vor dem Endtag des Formulars) gerendert. Auf diese Weise kann das Skript Seitenelemente aufrufen oder referenzieren, ohne sie möglicherweise nicht im DOM der Seite zu finden.

Hier ist die gerenderte Quelle der Seite, wenn Sie die RegisterStartupScript -Methode aufrufen:

<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. Wenn Sie RegisterClientScriptBlock verwenden, wird das Skript direkt nach dem Viewstate-Tag, jedoch vor einem der Seitenelemente gerendert. Da es sich um ein direktes Skript handelt (keine Funktion, die aufgerufen werden kann , wird es sofort vom Browser ausgeführt, aber der Browser findet die Bezeichnung nicht In diesem Stadium sollte im DOM der Seite die Fehlermeldung "Objekt nicht gefunden" angezeigt werden.

Hier ist die gerenderte Quelle der Seite, wenn Sie die RegisterClientScriptBlock -Methode aufrufen:

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

Zusammenfassend sollten Sie daher die letztere Methode aufrufen, wenn Sie eine Funktionsdefinition rendern möchten. Sie können dann den Aufruf dieser Funktion mit der vorherigen Methode rendern (oder ein clientseitiges Attribut hinzufügen).

Nach Kommentaren bearbeiten:


Zum Beispiel würde die folgende Funktion funktionieren:

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

Hier ist ein einfachstes Beispiel aus der ASP.NET-Community, das mir ein klares Verständnis für das Konzept gab.

welchen Unterschied macht das?

Ein Beispiel hierfür ist die folgende Methode, um den Fokus auf ein Textfeld auf einer Seite zu legen, wenn die Seite in den Browser geladen wird - mit Visual Basic unter Verwendung der RegisterStartupScript -Methode:

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

Dies funktioniert gut, da das Textfeld auf der Seite generiert und auf der Seite platziert wird, wenn der Browser den unteren Rand der Seite erreicht und auf dieses kleine Stück JavaScript zugreift.

Aber wenn es stattdessen so geschrieben wurde (mit der RegisterClientScriptBlock Methode):

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

Der Fokus wird nicht auf das Textfeld-Steuerelement gelegt, und auf der Seite wird ein JavaScript-Fehler generiert

Der Grund dafür ist, dass der Browser auf das JavaScript stößt, bevor sich das Textfeld auf der Seite befindet. Daher kann das JavaScript keine TextBox1 finden.

6
c-sharp user