ASP.NET Web Forms 提供 ClientScriptManager (Page.ClientScript) 統一管理客戶端腳本註冊,避免重複輸出、確保載入順序、支援部分更新。掌握其核心方法,能優雅整合 JavaScript 與伺服器端控制項。
| 方法 | 輸出位置 | 適用場景 | 關鍵參數 |
|---|---|---|---|
| RegisterClientScriptBlock | <form> 開始標籤後 | 定義函式、變數、類別 (需供後續腳本呼叫) | key, script, addScriptTags |
| RegisterStartupScript | </form> 結束標籤前 | 頁面載入完成立即執行 (alert、初始化 UI、綁定事件) | key, script, addScriptTags |
| RegisterOnSubmitStatement | form.onsubmit 事件 | 提交前驗證、攔截、記錄 | key, script |
| RegisterClientScriptInclude | <form> 後 | 引用外部 .js 檔案 | key, url |
| RegisterHiddenField | <form> 內 | 動態產生隱藏欄位傳遞資料 | name, value |
protected void Page_Load(object sender, EventArgs e)
{
// 1. 註冊共用函式庫 (僅輸出一次)
const string libKey = "CommonScripts";
if (!ClientScript.IsClientScriptBlockRegistered(libKey))
{
string lib = @"
function confirmAction(msg) { return confirm(msg || '確定執行?'); }
function showToast(msg, type) {
// 簡易 toast 實作或整合 toastr
alert('[Toast] ' + msg);
}
";
ClientScript.RegisterClientScriptBlock(this.GetType(), libKey, lib, true);
}
// 2. 按鈕點擊前確認 (注入 onclick)
btnDelete.Attributes["onclick"] = "return confirmAction('確定刪除此筆資料?');";
// 3. 非同步/同步完成後提示
if (IsPostBack && hdnActionResult.Value == "Success")
{
ClientScript.RegisterStartupScript(
this.GetType(),
"toastSuccess",
"showToast('操作成功!', 'success');",
true);
}
}
ClientScriptManager 在非同步回發時**不會**重新輸出 StartupScript,需改用 ScriptManager:
// 同步 Postback 或首次載入
ClientScript.RegisterStartupScript(type, key, script, true);
// 非同步回發 (UpdatePanel 內觸發)
ScriptManager.RegisterStartupScript(this, type, key, script, true);
// 判斷是否在非同步回發中
if (ScriptManager.GetCurrent(Page)?.IsInAsyncPostBack == true)
{
ScriptManager.RegisterStartupScript(...);
}
else
{
ClientScript.RegisterStartupScript(...);
}
IsClientScriptBlockRegistered(key):檢查 RegisterClientScriptBlock 是否已註冊IsStartupScriptRegistered(key):檢查 RegisterStartupScript 是否已註冊"{TypeName}_{FunctionalName}",如 "ProductList_InitDataTable"
var config = new
{
ApiBaseUrl = ResolveUrl("~/api/"),
PageSize = 20,
UserRole = CurrentUser.Role,
Tokens = new { AntiForgery = GetAntiForgeryToken() }
};
string script = $@"window.AppConfig = {JsonConvert.SerializeObject(config)};";
ClientScript.RegisterClientScriptBlock(this.GetType(), "AppConfig", script, true);
前端直接使用 window.AppConfig.ApiBaseUrl,避免內嵌 <%= %> 混亂 HTML/JS。
| 錯誤 | 正確做法 |
|---|---|
在 .aspx 內嵌 <script>alert('x')</script> | 用 RegisterStartupScript 確保位置正確、不重複 |
RegisterClientScriptBlock 用於 alert | alert 需 DOM 就緒,應用 RegisterStartupScript |
| Key 重複導致腳本覆蓋/遺失 | 每個功能區塊使用唯一 Key,善用 Is...Registered 檢查 |
| 非同步回發未觸發提示 | 改用 ScriptManager.RegisterStartupScript |
| 大量腳本內嵌導致頁面膨脹 | 改用 RegisterClientScriptInclude 參考外部 .js,啟用 Bundling/Minification |
System.Web.Optimization Bundling/MinificationClientScriptManager 仍是最穩健的整合方式。核心原則:**腳本註冊集中化、位置正確化、依賴明確化、重複零容忍。**