Разница между RegisterStartupScript и RegisterClientScriptBlock?

Единственное различие между RegisterStartupScript и RegisterClientScriptBlock заключается в том, что RegisterStartupScript помещает javascript перед закрывающим тегом </form> на странице, а RegisterClientScriptBlock помещает его сразу после стартового тега <form> на странице?

Кроме того, когда вы выбираете один над другим? Я написал краткую страницу с примерами, в которой у меня была проблема, и я не уверен, почему именно это происходит.

Вот разметка 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>

Вот код позади:

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

Проблема заключается в том, что когда я нажимаю кнопку btnPostBack, она выполняет обратную передачу и меняет ярлык на красный, но когда я нажимаю btnPostBack2, он выполняет обратную передачу, но цвет ярлыка не меняется на красный. Почему это? Это потому, что метка не инициализирована?

Я также читал, что если вы используете UpdatePanel, вам нужно использовать ScriptManager.RegisterStartupScript, но если у меня есть MasterPage, я бы использовал ScriptManagerProxy?

Ответ 1

Вот старая дискуссионная нить, в которой перечислены основные различия и условия, в которых вы должны использовать каждый из этих методов. Я думаю, вам будет полезно обсудить эту дискуссию.

Чтобы объяснить различия, относящиеся к вашему опубликованному примеру:

а. Когда вы используете RegisterStartupScript, он отобразит ваш script после всех элементов на странице (прямо перед тегом конца формы). Это позволяет script вызывать или ссылаться на элементы страницы без возможности их нахождения на странице DOM.

Вот рендеринг источника страницы при вызове метода 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>

б. Когда вы используете RegisterClientScriptBlock, script отображается сразу после тега Viewstate, но перед любым элементом страницы. Поскольку это прямой script (а не функция, которая может быть вызвана, она будет немедленно выполнена браузером. Но на этом этапе браузер не находит метку на странице DOM, и поэтому вы должны получить "Object not найденной".

Здесь представлен отображаемый источник страницы при вызове метода 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';

Поэтому, чтобы суммировать, вы должны вызвать последний метод, если вы намерены отобразить определение функции. Затем вы можете выполнить вызов этой функции с использованием прежнего метода (или добавить атрибут на стороне клиента).

Изменить после комментариев:


Например, будет работать следующая функция:

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

Ответ 2

Вот пример simpleest из сообщества ASP.NET, это дало мне четкое представление о концепции....

какая разница?

В качестве примера можно привести фокус на текстовое поле на странице при загрузке страницы в браузер - с помощью Visual Basic с помощью метода RegisterStartupScript:

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

Это хорошо работает, потому что текстовое поле на странице генерируется и помещается на страницу к моменту, когда браузер опустится до нижней части страницы и доберется до этого немного JavaScript.

Но если вместо этого оно было написано так (с использованием метода RegisterClientScriptBlock):

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

Фокус не попадет в элемент управления текстовыми полями, и на странице будет создана ошибка JavaScript.

Причиной этого является то, что браузер столкнется с JavaScript, прежде чем текстовое поле появится на странице. Поэтому JavaScript не сможет найти TextBox1.