Sự khác biệt giữa RegisterStartupScript và RegisterClientScriptBlock?


139

Có phải sự khác biệt duy nhất giữa RegisterStartupScriptRegisterClientScriptBlockđó là RegisterStartupScript đặt javascript trước </form>thẻ đóng của trang và RegisterClientScriptBlock đặt nó ngay sau <form>thẻ bắt đầu của trang?

Ngoài ra, khi nào bạn sẽ chọn cái này hơn cái kia? Tôi đã viết lên một trang mẫu nhanh nơi tôi gặp vấn đề và tôi không chắc lý do chính xác tại sao nó lại xảy ra.

Đây là đánh dấu 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>

Đây là mã đằng sau:

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

Vấn đề là khi tôi nhấp vào btnPostBacknút, nó sẽ quay lại và thay đổi nhãn thành màu đỏ, nhưng khi tôi nhấp vào btnPostBack2, nó sẽ quay lại, nhưng màu nhãn không chuyển sang màu đỏ. Tại sao lại thế này? Có phải vì nhãn không được khởi tạo?

Tôi cũng đọc rằng nếu bạn đang sử dụng UpdatePanel, bạn cần sử dụng ScriptManager.RegisterStartupScript, nhưng nếu tôi có MasterPage, tôi có sử dụng ScriptManagerProxykhông?

Câu trả lời:


162

Đây là một chủ đề thảo luận cũ , nơi tôi liệt kê các khác biệt chính và các điều kiện mà bạn nên sử dụng từng phương pháp này. Tôi nghĩ rằng bạn có thể thấy hữu ích để đi qua các cuộc thảo luận.

Để giải thích sự khác biệt có liên quan đến ví dụ được đăng của bạn:

a. Khi bạn sử dụng RegisterStartupScript, nó sẽ hiển thị tập lệnh của bạn sau tất cả các thành phần trong trang (ngay trước thẻ kết thúc của biểu mẫu). Điều này cho phép tập lệnh gọi hoặc tham chiếu các phần tử trang mà không có khả năng nó không tìm thấy chúng trong DOM của Trang.

Đây là nguồn kết xuất của trang khi bạn gọi RegisterStartupScriptphương thức:

<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. Khi bạn sử dụng RegisterClientScriptBlock, tập lệnh được hiển thị ngay sau thẻ Viewstate, nhưng trước bất kỳ thành phần nào của trang. Vì đây là tập lệnh trực tiếp (không phải là chức năng có thể được gọi , nên nó sẽ ngay lập tức được trình duyệt thực thi. Nhưng trình duyệt không tìm thấy nhãn trong DOM của Trang ở giai đoạn này và do đó bạn sẽ nhận được "Không tìm thấy đối tượng" lỗi.

Đây là nguồn kết xuất của trang khi bạn gọi RegisterClientScriptBlockphương thức:

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

Do đó, để tóm tắt, bạn nên gọi phương thức sau nếu bạn có ý định kết xuất một định nghĩa hàm. Sau đó, bạn có thể kết xuất cuộc gọi đến hàm đó bằng phương thức cũ (hoặc thêm thuộc tính phía máy khách).

Chỉnh sửa sau khi bình luận:


Chẳng hạn, chức năng sau sẽ hoạt động:

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
Bạn có thể giải thích thêm một chút về các chức năng nội tuyến.
Xaisoft

2
Chỉnh sửa bài viết của tôi để minh họa tốt hơn so với ví dụ của bạn.
Cerebrus

1
Tôi thực sự không gặp lỗi, cập nhật thời gian, nhưng màu sắc không thay đổi. Còn phần câu hỏi của tôi thì tôi hỏi tôi có phải sử dụng ScriptManagerProxy không nếu tôi đã xác định ScriptManager trong trang chính?
Xaisoft

1
Đã chỉnh sửa xong. Tôi không chắc chắn về lỗi với ScriptManagerProxy. Tôi nghĩ bạn nên đánh giá nếu đó không thực sự là một câu hỏi riêng biệt. ;-)
Cerebrus

1
Tuyệt quá! Cảm ơn cho đến nay. Tôi không gặp lỗi với ScriptManagerProxy. Tôi chỉ biết rằng bạn chỉ có thể khai báo một phiên bản của ScriptManager, vì vậy nếu tôi đã có ScriptManager được xác định trong trang chính, tôi sẽ giả sử rằng tôi sẽ sử dụng ScriptManagerProxy thay thế.
Xaisoft

6

Đây là một ví dụ đơn giản nhất từ Cộng đồng ASP.NET, điều này đã cho tôi hiểu rõ về khái niệm này ....

Điều này có gì khác biệt?

Ví dụ về điều này, đây là một cách để tập trung vào một hộp văn bản trên một trang khi trang được tải vào trình duyệt với ứng dụng Visual Basic RegisterStartupScript.

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

Điều này hoạt động tốt bởi vì hộp văn bản trên trang được tạo và được đặt trên trang vào thời điểm trình duyệt xuống cuối trang và nhận được một chút JavaScript này.

Nhưng, nếu thay vào đó, nó được viết như thế này (sử dụng RegisterClientScriptBlockphương thức):

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

Tập trung sẽ không nhận được điều khiển hộp văn bản và một lỗi JavaScript sẽ được tạo ra trên trang

Lý do cho điều này là trình duyệt sẽ gặp JavaScript trước khi hộp văn bản nằm trên trang. Do đó, JavaScript sẽ không thể tìm thấy TextBox1.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.