脚本注册
ASP.NET 2.0脚本支持
–不推荐,或者说不要使用Response.Write方法
不止是破坏了整个页面模型,特别是开发控件
–使用Framework所支持的方法
RegisterArrayDeclaration
RegisterClientScriptBlock
RegisterClientScriptInclude
RegisterClientScriptResource
RegisterExpandoAttribute
RegisterHiddenField
RegisterOnSubmitStatement
RegisterStartupScript
ClientScriptManager cs = this.ClientScript; //创建JavaScript数组 //<script type="text/javascript"> //<!-- //var Hello = new Array(1, 2, 3); --> //</script> //但当Array(5)的时候是表示长度为5的数组 cs.RegisterArrayDeclaration("Hello", "1", "2", "3"); //为对象输出一个函数,为true时自动加上<script></script> // <script type="text/javascript"> //<!-- //function helloWorld(){alert(1);}// --> //</script> cs.RegisterClientScriptBlock(this, GetType(), "HelloWorld", "function helloWorld(){alert(1);}",true); //添加对JS脚本的引用 //<script src="HelloWorld.js" type="text/javascript"></script> cs.RegisterClientScriptInclude("HelloWorld","HelloWorld.js"); //为指定控件添加额外的属性,一定要为ClientID,因为生成的在客户端表示不一样 //<script type="text/javascript"> //<!-- //var Button1 = document.all ? document.all["Button1"] : document.getElementById("Button1"); //Button1.Hello = "World"; --> //</script> cs.RegisterExpandoAttribute(this.Button1.ClientID,"Hellod","World"); //添加个隐藏值 //<input type="hidden" name="hello" id="hello" value="world" /> cs.RegisterHiddenField("Hello","World"); //confirm //<script type="text/javascript"> //<!-- //function WebForm_OnSubmit() { //return window.confirm('Do you really want to submit the form?'); //return true; //} --> //</script> cs.RegisterOnSubmitStatement(this.GetType(), "HelloWorld", "return window.confirm('Do you really want to submit the form?')"); //添加一个Script,最开始运行 //<script>alert('The page has loaded!')</script> cs.RegisterStartupScript(this.GetType(), "HelloWorld", "<script>alert('The page has loaded!')</script>"); |
•在异步更新的环境中注册脚本,所以当使用Response.Write();就会报错了
–使用ScriptManager对应的静态方法
–新方法与原有方法的区别:
•方法都会都接受一个参数
•并非所有注册过的脚本都会生效
•RegisterExpandoAttribute方法多了个encode参数
–新方法可以用来完全替换原有方法
•在非异步回送环境中会使用ClientScriptManager的对应方法进行注册
<asp:ScriptManager ID="ScriptManager1" runat="server"> </asp:ScriptManager> <asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <%= DateTime.Now %> <asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click1" /> </ContentTemplate> </asp:UpdatePanel> <asp:UpdatePanel ID="UpdatePanel2" runat="server" UpdateMode=Conditional> <ContentTemplate> <%= DateTime.Now %> </ContentTemplate> </asp:UpdatePanel> protected void Button1_Click1(object sender, EventArgs e) { ScriptManager.RegisterStartupScript(this.UpdatePanel1, this.GetType(), "UpdatePanel1", "alert(1)", true); ScriptManager.RegisterStartupScript(this.UpdatePanel2, this.GetType(), "UpdatePanel2", "alert(2)", true); } |
结果,当点击Button的时候,只刷新了UpdatePanel1.只有当UpdatePanel2的UpdateMode为Always或不写时才会更新
另,ScriptManager.RegisterStartupScript();也可以直接对整个PAGE操作了
l 错误处理
服务器端ScriptManager设置
–AllowCustomErrorsRedirect属性:遇到错误是否自动根据web.config中的设置跳转,默认值为True。
–AsyncPostBackError事件:异步刷新中出现错误时触发的事件。
–AsyncPostBackErrorMessage属性:客户端接受到的错误信息。
Web.Config中<customErrors mode="On" defaultRedirect="~/Error.aspx"></customErrors> Error.aspx为自定义错误 页面中 <asp:ScriptManager ID="ScriptManager1" runat="server" AllowCustomErrorsRedirect="true"> </asp:ScriptManager> |
<asp:ScriptManager ID="ScriptManager1" runat="server" AllowCustomErrorsRedirect="false" 当服务端抛出个异常的时候,会跳出一段XXXXXX的错误 添加如下事件 <asp:ScriptManager ID="ScriptManager1" runat="server" AllowCustomErrorsRedirect="false" OnAsyncPostBackError="ScriptManager1_AsyncPostBackError"> </asp:ScriptManager> protected void ScriptManager1_AsyncPostBackError(object sender, AsyncPostBackErrorEventArgs e) { ScriptManager.GetCurrent(this).AsyncPostBackErrorMessage = e.Exception.Message; } 但这样的话会弹出一个对话框 比如在页面中添加如下 <div id="error"></div> <script type="text/javascript" language="javascript"> Sys.WebForms.PageRequestManager.getInstance().add_endRequest(function(sender, e) { e.set_errorHandled(true); $get("error").innerHTML = "Sorry, an error has occurred: " + e.get_error().message; setTimeout(function(){ $get("error").innerHTML = ""; }, 3000); }); </script> |
客户端编程
–响应PageRequestManager的endRequest事件。
–将errorHandled属性设为true。
l 动态操作
要点:
–在生命周期的Load阶段结束之前动态添加控件
–为每个动态控件指定明确的ID
–不要为页面中的UpdatePanel添加新的Trigger
原因
–使用ContentTemplateContainer属性向UpdatePanel内添加新控件
protected void Page_Load(object sender, EventArgs e) { UpdatePanel up = new UpdatePanel(); up.ID = "UpdatePanel1"; this.Form.Controls.Add(up); LiteralControl lc = new LiteralControl(DateTime.Now.ToString()); up.ContentTemplateContainer.Controls.Add(lc); Button btn = new Button(); btn.Text = "Refresh"; up.ContentTemplateContainer.Controls.Add(btn); } |
演示:http://www.jeffzon.net/Samples/SwitchPartManager/Default.aspx
l 实现原理简要分析
传统的PostBack
Init
Load State
Process PostBack
PostBack Events
Save State
ProRender
Render
Upload
异步PostBack
- PageRequestManager -- ProRender
ProRender
Upload
请求内容数据大小没有任何减少
–采集Form中所有<input />并发送
–包含ViewState
尽可能减少客户端接受到的数据大小
–使用多个UpdatePanel包含多个部分
–UpdateMode尽量不要设为Always
什么样的UpdatePanel会更新?
–UpdateMode为Always
–AsyncPostBackTrigger的条件被满足
–Update方法被调用
–客户端告诉服务器端需要更新
ChildrenAsTriggers属性的效果体现在客户端
通过元素的ID、UniqueID与DOM结构共同判断
l 相关资源
官方站点:
ScottGuthrie的blog:
– http://weblogs.asp.net/scottgu/
WebCast AJAX作者视频blog:( 本系列视频都是参考此BLOG)
•MSDN中文网站http://www.microsoft.com/china/msdn
•MSDN中文网络广播http://www.msdnwebcast.com.cn
•MSDN Flash http://www.microsoft.com/china/newsletter/case/msdn.aspx
•MSDN开发中心 http://www.microsoft.com/china/msdn/DeveloperCenter/default.mspx