RegisterStartupScript 和 RegisterClientScriptBlock 之间的区别?

Posted

技术标签:

【中文标题】RegisterStartupScript 和 RegisterClientScriptBlock 之间的区别?【英文标题】:Difference between RegisterStartupScript and RegisterClientScriptBlock? 【发布时间】:2010-10-14 13:40:55 【问题描述】:

RegisterStartupScriptRegisterClientScriptBlock 之间的唯一区别是 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】:

Here's an old discussion thread 我列出了主要区别以及您应该使用这些方法的条件。我认为您可能会发现进行讨论很有用。

解释与您发布的示例相关的差异:

一个。当您使用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>

b.当您使用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';

因此,总而言之,如果您打算渲染函数定义,则应该调用后一种方法。然后,您可以使用前一种方法(或添加客户端属性)呈现 对该函数的调用

在 cmets 之后编辑:


例如,下面的函数会起作用:

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

【讨论】:

你能解释一下内联函数吗? 编辑我的帖子以更好地说明它与您的示例。 我其实没有报错,时间更新了,但是颜色没有变化。如果我在母版页中已经定义了 ScriptManager,我的问题中我问是否必须使用 ScriptManagerProxy 呢? 完成编辑。我不确定 ScriptManagerProxy 的错误。我认为你应该评估这是否真的不是一个单独的问题。 ;-) 太棒了!感谢到目前为止。我没有收到 ScriptManagerProxy 错误。我只知道你只能声明一个 ScriptManager 实例,所以如果我已经在母版页中定义了一个 ScriptManager,我会假设我会使用 ScriptManagerProxy。【参考方案2】:

这是一个来自 ASP.NET 社区的simplest 示例,这让我对这个概念有了一个清晰的理解......

这有什么不同?

例如,当页面加载到浏览器中时,以下是一种将焦点放在页面上的文本框的方法 - 在 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。

【讨论】:

以上是关于RegisterStartupScript 和 RegisterClientScriptBlock 之间的区别?的主要内容,如果未能解决你的问题,请参考以下文章

Response.Write RegisterClientScriptBlock和RegisterStartupScript总结

RegisterStartupScript 或 RegisterClientScriptBlock 哪个更快?

C# 从后台代码同步或异步注册Javascript到页面之RegisterStartupScript和RegisterClientScriptBlock的区别

无法使用 Response.Write 或 ClientScript.RegisterStartupScript 从代码后面打开新窗口

ScriptManager.RegisterStartupScript 不断添加脚本块多次

在 ScriptManager.RegisterStartupScript 后面的代码中调用脚本后,jQuery document.ready 不会触发