Різниця між RegisterStartupScript і RegisterClientScriptBlock?


139

Єдина різниця між 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?

Відповіді:


162

Ось старий порядок обговорення, де я перерахував основні відмінності та умови, в яких слід використовувати кожен із цих методів. Я думаю, що вам може бути корисним пройти дискусію.

Щоб пояснити відмінності як відповідні для розміщеного прикладу:

а. Коли ви користуєтесь RegisterStartupScript, він відобразить ваш сценарій після всіх елементів сторінки (безпосередньо перед кінцевим тегом форми). Це дозволяє скрипту викликати елементи виклику або довідкової сторінки без можливості того, щоб вони не знаходили їх у 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сценарій відображається відразу після тегу Viewstate, але перед будь-яким із елементів сторінки. Оскільки це прямий скрипт (не функція, яку не можна викликати , він буде негайно виконуватися браузером. Але браузер не знайде мітку в DOM сторінки на цьому етапі, отже, ви повинні отримати "Об'єкт не знайдено" помилка.

Ось надане джерело сторінки, коли ви викликаєте 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); 
  } 
} 

1
Чи можете ви пояснити трохи більше про вбудовані функції.
Xaisoft

2
Редагування моєї публікації, щоб краще проілюструвати її на прикладі.
Церебрус

1
Я фактично не отримую помилку, час оновлюється, але колір не змінюється. Що з частиною мого запитання, де я запитую, чи потрібно використовувати ScriptManagerProxy, якщо у мене вже визначений ScriptManager на головній сторінці?
Xaisoft

1
Виконано редагування. Я не впевнений у помилці з ScriptManagerProxy. Я думаю, ви повинні оцінити, чи це насправді не окреме питання. ;-)
Церебрус

1
Чудово! Дякую поки що. Я не отримую помилку з ScriptManagerProxy. Я просто знаю, що ви можете оголосити лише один екземпляр ScriptManager, тому, якщо у мене вже є ScriptManager, визначений, наприклад, на головній сторінці, я б припустив, що я б замість цього використовував ScriptManagerProxy.
Xaisoft

6

Ось найпростіший приклад спільноти 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.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.