asp.net中的AJAX编程-ASP.NET AJAX框架

   这一篇讲述Ajax的原理,包括XMLHttpReuqest构建一个异步的应用。另外,解释包括ASP.NET AJAX的架构。Microsoft AJAX Library开发主要分为两个部分,分别是客户端的开发和服务器端的开发,这里介绍的他们之间的区别。
   主要重点介绍了Microsoft Ajax Libary库,包括Application模型、DOM模型、客户委托、回调、还说明Javascript内置的一些对象如String,Date,Array在Microsoft Ajax Libary中的扩展。

1. XMLHttpRequest对象

     XMLHttpRequest对象是Ajax编程的核心,正是这个对象支持Javascript向服务器发出请求并处理响应。
     以下是使用XMLHttpRequest技术向服务器异步提交一个请求,并得到响应的一个示例,示例由两个文件组成:
       ● XMLHttpRequest.aspx : 页面载入后,异步的向服务器递交一个GET请求,请求载入另外一个页面中的内容
       ● Welcome.htm : 被XMLHttpRequest.aspx所要求的页面。
例1: 使用XMLHttpRequest构造AJAX程序,
=== XMLHttpRequest.aspx ===

ContractedBlock.gifExpandedBlockStart.gifCode
<!-- 页面中包括一个results的span,和一段Javascript脚本 -->

<span id="results">loading</span>

<script language="javascript" type="text/javascript">

   
var xmlHttp = null
;

   
// 设置xmlHttpRequest对象,

    function
loadXmlHttp() {
       
if (window.XMLHttpRequest) { // IE7,Mozilla,Safali..

            xmlHttp = new
XMLHttpRequest();
        }
else if
(window.ActiveXObject) {
            xmlHttp
= new ActiveXObject("Microsoft.XMLHTTP"
);
        }
else
{
        }
    }

   
function
sendRequest(url, callbackfunction) {
       
if
(xmlHttp) {
            xmlHttp.open(
"GET", url, true);  // true表示打开异步连接

            xmlHttp.onreadystatechange = callbackfunction;  // 指定回调函数

            xmlHttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); // 发送请求头部信息

            xmlHttp.send(null); // 发送异步请求

        }else

            alert(
'xmlHttp is null'
);
    }

   
// 页面载入时动作: 设定xmlHttp对象,异步发送请求到Welcome.htm。

    window.onload = function
() {
        loadXmlHttp();
        sendRequest(
"Welcome.htm"
, oncallback);
    }

   
// 回调函数,异步请求成功后,会调用这个回调函数。

    // 基中xmlHttp.readyState=4表示就绪状态,xmlHttp.status==200表示成功请求

    // xmlHttp.responseText表示请求的结果。

    function
oncallback() {
       
if (xmlHttp.readyState == 4
) {
           
if (xmlHttp.status == 200) {  // 这里两个if必须分开来,因为异步有多次函数调用。

                var r = document.getElementById('results'
);
                r.innerHTML
=
xmlHttp.responseText;
            }
else
{
                alert(
'Error:' +
xmlHttp.status);
            }
        }
    }
</script> 

=== Welcome.htm ===

<body>
   
<div>Welcome to this Page</div>

   
<div>hope you loving it</div>

</body>


2. ASP.NET AJAX架构

    ASP.NET AJAX框架能够支持开发人员创建有丰富内容,具有交互性,高度个性化的WEB页面,并且能够跨浏览器兼容。它是一个Ajax库。
    AJAX框架涵盖了客户端和服务器端,整个框架如下图所示:
aspnet_ajax_framework

    2.1 客户端框架
        客户端框不依赖于服务器组件,它的核心是Microsoft Ajax Library(Microsoft Ajax库),也称核心(core)库。这个库由一组Javascript组成,文件可以独立于服务器特性使用(即只要把文件导入进来,php,asp都可以使用该JS库)。
          ● Type System : 核心库最基础的就是类型系统(Type System),它引入了我们熟悉的面向对象的编程概念,如类、继承、接口、事件等模型。也扩展了现有的Javascript类型(如String,Array类型等)
          ● Componets : 类型系统之上是组件层,完成核心库的大部分主要工作。该层提供JSON串行化,网络通信,本地化,DOM交互和ASP.NET应用服务。
          ● Application : 类型于ASP.NET中的页面生命周期,该层提供了事件驱动编程模型,可以用来在浏览器中处理DOM元素、组件和应用程序的生命周期。
        除了核心库外,它还包括了HTML,Javascript,XML Script、ASP.NET AJAX服务代理。
          ● HTML,Javascript,XML Script为客户端代码提供多种选择,可以采用声明方式利用XML Script编写代码,也可以使用命令方式使用JS编写代码..
          ● ASP.NET AJAX Web Service Proxies : 提供了可以从JS通过一组由服务器生成的客户端代理调用WEB服务。这个以后会讲到。

     2.2 服务端框架
        服务端框架中主要的一层为ASP.NET AJAX服务器扩展(ASP.NET AJAX Server Extensions),它包括了3个方面,分别为:
          ● ASP.NET AJAX Server Controls : 包括平常使用的ScriptManager,UpdatePannel,Timer控件,利用它们可以很方便的在ASP.NET程序中实现AJAX应用。
          ● Web Service Bridge : WEB服务桥,可以利用它创建一个网关,允许客户端脚本调用外部的WEB服务。
          ● App Service Bridge : 应用服务桥,可以利用它与ASP.NET紧密集成,如用户验证,个性化。


      2.3.简单的以服务器中心的解决方案

       以服务器为中心的解决方案主要是使用ScriptManager,UpdatePannel,UpdateProgress等相关的控件,达到在一个页面中的某个区域进行更新。
例2: 简单的服务器为中心的AJAX例程

ContractedBlock.gifExpandedBlockStart.gifShowEmployees.aspx
<script runat="server">

   
/* 一个简单的返回部门中人数的静态类 */

    public static class HumanResources
    {
        public static
int GetEmployeeCount(string department)
        {
           
int count = 0
;
           
switch
(department)
            {
               
case "Sales"
:
                    count
= 10; break
;
               
case "Engineering"
:
                    count
= 20; break
;
               
case "Marketing"
:
                    count
= 44; break
;
               
case "HR"
:
                    count
= 7; break
;
               
default
:
                   
break
;
            }
           
return
count;
        }
    }

   
/* 当用户点击ListBox中的某一项时,Label中的文字变更,线程暂停1秒,以用来显示UpdateProgress控件中的内容 */

    protected
void
Departments_SelectedIndexChanged(object sender, EventArgs e)
    {
        EmployeeResults.Text
= string.Format("Empoyee count:{0}"
, HumanResources.GetEmployeeCount(Departments.SelectedValue));
        System.Threading.Thread.Sleep(
1000
);
    }
</script>

<body>

   
<form id="form1" runat="server">

   
<div>

       
<!-- ScriptManager控件为Ajax在页面中的大脑中枢,必须存在 -->

       
<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>

       
<!-- UpdatePanel:可以动态进行异步更新的区域 -->

       
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">

       
<ContentTemplate>

           
<asp:ListBox ID="Departments" runat="server" Height="98px"

                onselectedindexchanged
="Departments_SelectedIndexChanged"

                AutoPostBack
="True">

               
<asp:ListItem>Engineering</asp:ListItem>

               
<asp:ListItem>HR</asp:ListItem>

               
<asp:ListItem>Sales</asp:ListItem>

               
<asp:ListItem>Marketing</asp:ListItem>

           
</asp:ListBox>

           
<asp:Label ID="EmployeeResults" runat="server" Text="Label"></asp:Label>

       
</ContentTemplate>

       
</asp:UpdatePanel>

       
<!--当UpdatePanel中的内容回送后,动作完成之前,显示loading..动画 -->

       
<asp:UpdateProgress ID="UpdateProgress1" runat="server">

       
<ProgressTemplate>

           
<asp:Image ID="Image1" runat="server" ImageUrl="~/img/icon/loading/loading2.gif" />
loading
       
</ProgressTemplate>

       
</asp:UpdateProgress>

   
</div>

   
</form>

</body> 


    2.4. 简单的以客户端为中心的解决方案

    服务器为中心的方式优点是简单透明,但客户端为中心的方式却是更加灵活,更加有效率。客户端为中心的解决方案,包括两个文件:
    GetEmployees_ClientMethod.aspx: 通过在页面上发生的事件,JS把参数发到相应的WebService上,并取得相应的返回值,显示在页面上。
    HRServices.asmx: 一个WebService,接受一个部门字符串,并返回部门的相应人数
例3:客户端为中心的解决方案

ContractedBlock.gifExpandedBlockStart.gifHRServices.asmx
using
System;
using
System.Web;
using
System.Web.Services;
using
System.Web.Services.Protocols;
using System.Web.Script.Services;  // 脚本服务的命名空间


public static class HumanResources
{
   
public static int GetEmployeeCount(string
department)
    {
       
int count = 0
;
       
switch
(department)
        {
           
case "Sales"
:
                count
= 10; break
;
           
case "Engineering"
:
                count
= 20; break
;
           
case "Marketing"
:
                count
= 44; break
;
           
case "HR"
:
                count
= 7; break
;
           
default
:
               
break
;
        }
       
return
count;
    }
}

[WebService(Namespace
= "http://tempuri.org/"
)]
[WebServiceBinding(ConformsTo
=
WsiProfiles.BasicProfile1_1)]
//若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消对下行的注释。

[System.Web.Script.Services.ScriptService]
public class
HRServices  : System.Web.Services.WebService {
    [ScriptMethod]  
// 声明脚本支持的有关特性

    [WebMethod]
   
public int GetEmployeeCount(string
department)
    {
       
return
HumanResources.GetEmployeeCount(department);
    }
}


ContractedBlock.gifExpandedBlockStart.gifGetEmployees_ClientMethod.aspx
<body>

   
<form id="form1" runat="server">

   
<div>

       
<!-- ScriptManager中调用<Services>一节用来引用Web服务代理 -->

       
<asp:ScriptManager ID="ScriptManager1" runat="server">

          
<Services>

           
<asp:ServiceReference Path="~/AJAX/AJAX_In_Action/Chapter2/HRServices.asmx" />
 
          
</Services>

       
</asp:ScriptManager>

       
<!-- 以下JS代码必须在ScriptManger定义之后,否则会出现Sys对象找不到的错误 -->

       
<script type="text/javascript" language="javascript">

           
var departments = null
;
           
/*注册加载(load)和卸载(unload)事件*/

            Sys.Application.add_load(page_load);
            Sys.Application.add_unload(page_unload);

           
//加载事件
            function
page_load(sender, e) {
               
// 取得部门列表,给列表加入事件

                departments = $get("Departments"
);
                $addHandler(departments,
"change"
, departments_onchange);
                alert(
'vvv'
);
            }

           
//卸载(unload)事件

            function
page_unload(sender, e) {
                $removeHandler(departments,
"change"
, departments_onchange);
            }

           
// Departments选框改变后的事件

            function
departments_onchange(sender, e) {
                $get(
"employeeResults").innerHTML = ""
;
                $get(
"loading").style.display = "block"
;
               
var selectedValue =
departments.value;
                HRServices.GetEmployeeCount(selectedValue, onSuccess);
// 调用Javascript代理

            }

           
// 代理调用成功后,result获得的调用Web服务中相应函数得到的结果

            function
onSuccess(result) {
                $get(
"loading").style.display = "none"
;
                $get(
"employeeResults").innerHTML = "Employee Count:" +
result;
            }
   
</script>

       
<!-- 注意下面,不会使用asp.net服务器控件,全部是HTML控件 -->

       
<select id="Departments" size="5">  <!-- 部门列表 -->

           
<option value="Engineering">Engineering</option>

           
<option value="HR">HR</option>

           
<option value="Sales">Sales</option>

           
<option value="Marketing">Marketing</option>

       
</select>

       
<br />

       
<span id="employeeResults"></span> <!-- 显示结果的span -->

       
<span id="loading" style="display:none">    <!-- 显示loading的span -->

       
<img alt="loadingImg" src="http://www.cnblogs.com/../img/icon/loading/loading2.gif" />
loading
       
</span>

   
</div>

   
</form>

</body> 


    以上,JS页面通过ScriptManger的<Service>属性把相应的参数递送到WebService中,然后,调用成功后,onSuccess回调函数会被调用,从onSuccess函数的result参数中得到相应的返回值。

3. Microsoft Ajax Libary 简介

    上面提到过,Microsoft Ajax Libary就是一个Microsoft Ajax库,也称核心(core)库,由一组Javascript代码构成。是客户端编程很重要的一部分,但是,它提供了哪些特性,其组成又是什么样的呢?下面主要谈论的就是这个库。
   这个库设计的主要目标不只是使用XMLHttpRequest对象异步请求的简单框架。实际上,它主要目标是为客户端提供.NET开发人员所熟悉的一些编码模式。利用这些与.NET类似的特性,可以在JS对象中组播事件、利用组件模型、面向对象和接口等等来构造客户代码,此外,还可以在JS中轻松访问本地WEB服务(例3所示),处理asp.net应用程序服务…

   3.1 Microsoft Ajax Libary特性
      Microsoft Ajax Libary按特性可以划分为几类。这几类在以后中会分别谈到,这里只是个概览
       ● Application模型:网页上启动Microsoft Ajax Libary时(就是在页面中加入ScriptManger控件),就会在运行时创建一个Application对象。该对象负责管理一个页面的客户生命周期,作用类似于服务器的Page对象(也可参考例3,其中的Sys.Application)
       ● 组件(Components): Libaray为客户端提供了一个组件模型,非常类似于.NET提供的组件模型,包括可视化组件和非可视化组件。这个在以后章节中专门讨论。
       ● Javascript扩展: 库利用了Javascript的对象模型,并改进了相应的类型系统,比如,支持继承、接口。改进了Array,String对象..
       ● 兼容性(Compatibility): 提供了一个抽象的API(abstraction API),可以用来编写“通用”的代码,在各个浏览器上都能平稳运行
       ● 应用服务: 可以使ASP.NET开发人员在客户端处理验证、成员和个性化等服务提供者。
       ● 部分更新: 利用UpdatePanel控件,无需刷新整个UI,可以更新页面布局的某些部分。在服务器端编程中是利用UpdatePanel,而在客户端,可以利用PageRequestManger对象来实现这种机制。

    3.2 Microsoft Ajax Library中定义的命名空间 
        图2介绍了在 Microsoft AJAX Library 中定义的所有 JavaScript 类。固有的 JavaScript 对象(如 Boolean、Date 和 Number)已得到扩展,包括了新的方法和功能。
图2: Microsoft AJAX Library 内置类

固有

说明

Array使用新的搜索方法扩展本机 Array 对象。
Boolean使用分析方法扩展本机 Boolean 对象。
Date使用格式化方法扩展本机 Date 对象。
Error扩展本机 Error 对象以使其与托管的异常对象类似。同时公开静态属性以映射错误的预定义类型。
Function使用委托和实用程序扩展本机 Function 对象以检查方法签名。
Object使用类型信息扩展本机 Object 对象。
Number使用分析和格式化方法扩展本机 Number 对象。
RegExp本机 RegExp 对象的简单包装。
String使用格式化方法扩展本机 String 对象。
Type对所有 OOP 扩展进行分组的函数别名。
Sys.UI 命名空间处理组件和DOM的类
Sys.UI.Behavior定义用来扩展新的和现有的 ASP.NET 服务器控件功能的行为基础。
Sys.UI.Bounds通过上-左-下-右参数定义页面中的区域。
Sys.UI.Control定义 Microsoft AJAX Library 用户界面控件的基础。
Sys.UI.DomElement用于页面中呈现的 DOM 元素的包装类。
Sys.UI.DomEvent用于 DOM 级别的事件(如按键或鼠标移动)的包装类。
Sys.UI.Point通过 (x,y) 坐标定义页面中的点。
基础类运行时基类,有Application对象等
Sys.Component定义 Microsoft AJAX Library 用户界面组件的基础。
Sys.CultureInfo定义文化信息。
Sys._Application表示当前页面的生命周期的内部类。
Sys._Debug提供调试服务的内部类。
Sys._ScriptLoader负责加载外部脚本的内部类。
网络类基于网络层的类
Sys.Net.NetworkRequestEventArgs定义与 Web 请求事件关联的数据。
Sys.Net._WebRequestManager内部类,表示用来设置全局参数(如执行器和超时)的 Web 请求的集中化管理器。
Sys.Net.WebRequest表示正在进行的 Web 请求。
Sys.Net.WebRequestExecutor表示负责实际执行 Web 请求的对象。
Sys.Net.WebServiceError用于在服务调用期间发生的任何异常的包装类。
Sys.Net.WebServiceProxy定义远程服务的 JavaScript proxy 类的基础。
Sys.Net.XMLHttpExecutor表示使用 XMLHttpRequest 的 Web 请求执行器。
服务帮助器类访问个性化、成员和验证等ASP.NET服务的类
Sys.Services._AuthenticationService用于服务器端验证 Web 服务的内部包装类。
Sys.Services._ProfileService用于服务器端用户配置文件 Web 服务的内部包装类。
Sys.Services._RoleService用于服务器端角色 Web 服务的内部包装类。仅在 ASP.NET 3.5 中提供了此类。
Sys.Services.ProfileGroup用来包含有关配置文件组的信息。
事件数据类提供客户端相应事件的类
Sys.ApplicationLoadEventArgs定义与 pageLoad 事件关联的数据。
Sys.CancelEventArgs定义任何可中断事件的数据对象的基础。
Sys.EventArgs定义任何事件的数据对象的基础。
Sys.EventHandlerList用来收集与执行 Web 请求关联的所有事件的帮助器类。
Sys.PropertyChangedEventArgs定义与 Microsoft AJAX Library 组件属性已更改的事件关联的数据。
实用程序Serialization表示完成JSON串行化/逆串行化的类,StringBuilder字符串扩展的类
Sys.Serialization.JavaScriptSerializer用来反序列化插入页面和 Sys.CultureInfo 对象使用的特殊数据的帮助器类。
Sys.StringBuilder用来连接字符串,该对象的工作方式与托管的 StringBuilder 类十分相似。
部分呈现类与部分页在更新有关的类
Sys.WebForms.PageRequestManager编排任何部分呈现请求和操作的根对象。
Sys.WebForms.PageLoadingEventArgs定义与 pageLoading 事件关联的数据。
Sys.WebForms.PageLoadedEventArgs定义与 pageLoaded 事件关联的数据。
Sys.WebForms.InitializeRequestEventArgs定义与 initializeRequest 事件关联的数据。
Sys.WebForms.EndRequestEventArgs定义与 endRequest 事件关联的数据。
Sys.WebForms.BeginRequestEventArgs定义与 beginRequest 事件关联的数据。
Sys.UI._UpdateProgress执行更新进度操作的客户端类。
Sys.UI._UpdateProgress执行更新进度操作的客户端类。


    3.3 Application 模型
        Microsoft Ajax Libary提供了Application模型,其类似于.net中的Page模型。在ASP.NET中,Page类是一个实例 ,Page类封装了控件层次体系。页面生命周期是从创建Page实例开始的一组处理步骤,包含多个阶段,由初始化→控件实例化→初始化属性→显示(Render)→撤销(Dispose).然后页面HTML写入响应流,并释放所有控件资源及Page实例本身。
        WEB页在服务器端完成了它的生命周期,页面的HTML准备就绪,就会下发给客户端浏览器。如果启用了Microsoft Ajax Libaray,就会在客户端开始一个新的生命周期。客户端加载HTML时,就会加载主脚本文件(MicrosoftAjax.js), 此时运行时库就会创建一个全局JS对象,即Application对象。这个对象全名为Sys.Application。
        Sys.Application与Page对象很相似,其创建的主要目标就是希望服务器端和客户端所用的编程模型能够一致。
        客户端页面有生命周期,从加载页面开始,到用户从页面导航到其它页面或卸载该页面时结束。这个周期中的各个阶段,Application对象都会产生一个相应的事件。
        关于页面的生命周期如图3所示,具体的会在 [
4. 客户页面的生命周期] 进行讨论
图3:Page模型->Application模型示例图
sys_application_model

     3.4 客户组件(Client components)
        如果一段JS/C#代码实现了一个特定的功能(如实现了一个深层次菜单),通常不解实现的具体逻辑,只需要配置相应的菜单,在页面中实例化即可。在另一个页面上使用,也只要实现类似的步骤(加入菜单项并初始化)。这里关键的一点是: 这些代码要打包到一个配置的对象中,这个对象能够在另一处重用。
        所以组件的概念就出来了:组件的原则是代码重用,其实现了一组明确定义的接口,允许与其它组件交互,而且可以在不同应用程序之间互换。有这样的基本接口,可以在任何时刻改变组件封装的代码而不会影响其处理逻辑。
        Microsoft Ajax Libary提供了一些专用的客户类,简化了客户组件的开发。与组件开发相关的一组类称为客户组件模型(client component model). 通过它,可以使用JS编写面向组件的客户端应用。
        客户组件相当于一个黑盒子,其中封装了一些可重用的客户逻辑,另外它通过一些方法、属性和事件来公开这些逻辑。如图4所示:
图4:客户组件图:
client_components

4. 客户页面的生命周期

    一个页面的生命周期是由Sys.Application来进行管理的,它的生命周期虽然类似于.net中的Page对象,但比Page对象的周期要简单的多。
    客户生命周期只包含3个阶段:   初始化(init),加载(load),卸载(unload)
    进入各个阶段,Sys.Application会触发相应的事件:init,load,unload.
    整个顺序过程如图5所示:
图5:客户页面生命周期
application_cricle

    
例4: 客户生命周期代码:

ContractedBlock.gif ExpandedBlockStart.gif Ajax.Sys.Application
<script type="text/javascript" language="javascript">
    Sys.Application.add_init(pageInit); 
// 注册pageInit事件
    function pageInit() {
        alert(
"Entered the Init state;");
    }

   
// 对于pageLoad与pageUnload无需像pageInit函数一样注册事件,当然也可以像例3一样进行注册
    // 如果不注册,即是默认的pageLoad与pageUnload()函数
    function pageLoad() {
        alert(
"Loading page!");
    }

   
function pageUnload() {
        alert(
"Unloading page");      
    }

</script>


5. 使用DOM

    浏览器显示一个页面时,会为所有HTML元素构建一个层次表(称为DOM树),页面中每个元素都会成为这个DOM树中的一个可编程控件,并暴露相应的属性、方法和事件。

   5.1 操作DOM的抽象APISys.UI.DomElement和Sys.UI.DomEvent
   几乎所有的浏览器都以不同的方式实现了自己的DOM编程接口,在这种情况下,Microsoft Ajax Libary提供了一个抽像的API来解决这个问题。这个API的作用是将DOM元素的一些公共操作抽象出来,利用这些API,无需了解一个特定的浏览器DOM实现支持哪些函数。
   独立于浏览器方式访问DOM,这个抽象API由两个客户类完成: Sys.UI.DomElement和Sys.UI.DomEvent提供的方法组成.
   比如,假设想对Dom元素绑定一个事件,不必检查浏览器支持的是attachEvent方法还是addEventListener方法,只需调用Sys.UI.DoElement类的addHandler方法即可。Sys.UI.DoElement.addHandler方法可以简写成$addHandler形式。以下是抽象API中常用方法的简写形式:
图6: 抽象API中常用方法的相应快捷命令:
domElement_shortcut 

图7:Sys.UI.DomElement包括方法如下图所示:
domElement_methods 

图8: Sys.UI.DomEvent包括的方法和属性如下所示:
domEvents_methods

例5: 只接受字母的文本框

ContractedBlock.gif ExpandedBlockStart.gif Ajax.txtNodigits
<script type="text/javascript" language="javascript">

   
// 对于pageLoad与pageUnload无需像pageInit函数一样注册事件,当然也可以像例3一样进行注册
    // 如果不注册,即是默认的pageLoad与pageUnload()函数
    function pageLoad() {
       
var txtNoDigits = $get("txtNoDigits");  // 获得页面中TextBox的DOM对象
        $addHandler(txtNoDigits, 'keypress', txtNoDigits_keypress);  //为该TextBox加入事件
    }

   
function pageUnload() {
        $removeHandler(txtNoDigits,
'keypress', txtNoDigits_keypress);  // 移除事件
    }

   
function txtNoDigits_keypress(evt) {
       
var code = evt.charCode;
       
if (code >= 48 && code <= 57) //如果是digits ,什么都不做。
            evt.preventDefault();
    }

</script>

 

对于$addHandler,原型如下:
    $addHandler(txtNogiits,’keypress’,txtNoDigits_keypress);
其中,第一个参数表示的是DOM元素,keypress表示事件名,事件名前不能含前缀on,txtNoDigits_keypress表示的是处理函数,注意,不能用引号括起来,也不能在后面加().

    5.2 CSS与定位
         可以通过Sys.UI.DomElement.addCssClass方法传入一个DOM元素,并提供一个表示CSS类名的字符串,就可以设置该DOM元素的CSS样式. 相反的通过removeCssClass方法,可以去除一个DOM元素的CSS样式,例如:
例6: 通过Sys.UI.DomElement.addCssClass设置DOM的CSS样式
ContractedBlock.gif ExpandedBlockStart.gif Ajax.addCssClass
<style type="text/css">
.textBoxStyle
{
     width
:76px;
     border
:0px;
     border-bottom
:1px solid #000000;
}
</style>
<asp:ScriptManager ID="ScriptManager1" runat="server"> </asp:ScriptManager> <!-- ScriptManager必须存在 -->
<input id="txtNoDigits" type="text" />
<script type="text/javascript" language="javascript">        
function pageLoad() {
    Sys.UI.DomElement.addCssClass($get(
'txtNoDigits'), 'textBoxStyle');
}
</script> 

     可以通过Sys.UI.DomElement.getLocation(element)方法来获得DOM元素的位置,返回一个对象,返回的对象包含两个属性x,y。表示相对于其父窗口的左上角的左、上坐标.通过setLocation(element,x,y)可以设置一个DOM元素的坐标位置
     可以通过Sys.UI.DomElement.getBound(element)获得一个对象,包含DOM元素的4个属性:x,y,height,width.


6.客户委托

    6.1 创建委托
         首先,创建客户委托如下:

    var handler = Function.createDelegate( this , this .myMethod);  // 这里创建委托
    $addhander(element,’event’,handler);  // 这里使用委托

         对于委托,尤其要注意的是this关键字,在一般的事件处理程序中,this关键字总是指向发生事件的对象。看以下示例:

ContractedBlock.gif ExpandedBlockStart.gif ClientNormalSample
<input id="Button1" type="button" value="ClickMe" />  <!-- 创建一个Button -->
<script language="javascript">
   
function pageLoad() {
       
this.Message = "I'm test string";
        $addHandler($get(
'Button1'), 'click', onClick);  // 普通的事件处理
    }

   
function onClick(event) {
        alert(
this.value);  //被调用后,这里的this就Button对象,这里输出"ClickMe"
    }   
</script>

         而如果使用客户委托,在事件处理程序中,this关键字在相应的被调用函数中就不是发生事件的对象了, 而是在客户委托函数第一个参数中指定的对象

ContractedBlock.gif ExpandedBlockStart.gif Ajax.ClientDelegateSample_1
<input id="Button1" type="button" value="ClickMe" />  <!-- 创建一个Button -->
<script language="javascript">
   
function pageLoad() {
       
this.Message = "I'm test string";
       
var ClickDelegate = Function.createDelegate(this, onClick);  // 创建客户委托,其中第一个参数为pageLoad对象。
        $addHandler($get('Button1'), 'click', ClickDelegate);  // 委托事件处理
    }

   
function onClick(event) {
        alert(
this.Message);  //被调用后,这里的this就pageLoad对象,这里输出I'm test string
    }
</script>

         以上看出,在事件处理程序(onClick)中,this关键字指向的对象变了,已经不是Button1对象,而是pageLoad一个对象。
         同样的,在创建委托函数中,第一个参数可以指定任何对象,比如以下示例:

ContractedBlock.gif ExpandedBlockStart.gif Ajax.ClientDelegateSample_2
<input id="Button1" type="button" value="ClickMe" />  <!-- 创建一个Button -->
<input id="Text1" type="text" />  <!-- 创建一个TextBox -->
<script language="javascript">
   
function pageLoad() {
       
this.Message = "I'm test string";
       
var ClickDelegate = Function.createDelegate($get('Text1'), onClick);  // 创建客户委托,其中第一个参数为Text1对象。
        $addHandler($get('Button1'), 'click', ClickDelegate);  // 委托事件处理
    }

   
function onClick(event) {
        alert(
this.value);  //被调用后,这里的this就Text1对象,这里输出Text1中的值
    }
</script>


    6.2 addHandlers与$clearHandlers
          使用addHandlers与clearHandlers优点是可以以很简单的方式创建委托,并关联处理程序。看一下示例:

ContractedBlock.gif ExpandedBlockStart.gif Ajax.addHander
<script language="javascript">
   
function pageLoad() {
       
this.Message = "I'm test string";
       
//var ClickDelegate = Function.createDelegate($get('Text1'), onClick);  // 创建客户委托,其中第一个参数为Text1对象。
        //$addHandler($get('Button1'), 'click', ClickDelegate);  // 委托事件处理
        //var mouseDelegate = Function.createDeletgate($get('Text1'),onMouseover);
        //$addHandler($get('Button1'),’mouseover’,mouseDelegate);
        $addHandlers($get('Button1'), { click: onClick,mouseover: onMouseover }, $get('Text1'));  //使用addHanders可以直接代替以上四行程序
    }

   
function onClick(event) {
        alert(
this.value);  //被调用后,这里的this就Text1对象,这里输出Text1中的值
    }
   
function onMouseover(event) {
        
// mouseover事件的处理
    }
</script>
Sample

         使用clearHandles可以将所有事件处理程序与元素解除关联,只需要一条语句:

   $clearHandlers(buttonElement);


7. 函数回调

     Microsoft Ajax Library提供了一个名为Function.createCallback方法,可以用这个方法创建一个回调函数,供对象在任何时刻调用。
     Function.createCallback的主要作用是基于一个上下文调用函数,这个上下文由创建该回调用的对象提供,通常,上下文就是一个对象,上下文的作用就是能够包含一个在正常情况下在方法中无法访问的一些应用数据(因为这些数据属于另一个作用载)。
      以上例子提供了一个回调函数的用法:

ContractedBlock.gif ExpandedBlockStart.gif Ajax.CallbackSample
<script type="text/javascript">
<!--
function pageLoad() {
   
var context = { date : new Date() };
   
var clickCallback = Function.createCallback(onButtonClick, context);  //创建回调函数,上下文为pageLoad作用域内的context。
    $addHandler($get('myButton'), 'click', clickCallback);
}
function onButtonClick(evt, context) {
   
var loadTime = context.date;
   
var elapsed = new Date() - loadTime;
    alert((elapsed
/ 1000) + ' seconds');
}
//-->
</script> 
8.Microsoft Ajax Library中的内置对象

   Javascript中的内置对象包括如Array,Date,String,Number,RegExp..它们在ECMAScript中都提供了一些相应的方法和属性。在Microsoft Ajax Library中,为了提高开必人员的生产力,扩展了这些对象,下面看看这些类扩展了哪些属性和方法
   8.1 Array对象的扩展方法
arrayobject

   以上add,addRange,enqueue提供了新增Item或Array的方法,clear,dequeue,remove,removeAt提供了删除元素的方法..这里就不介绍了,具体的可以看《Microsoft.AJAX.Library.Essentials》这本书。最后的附录有很好的介绍
   
     8.2 Date对象的扩展方法
dateobject 
      以上,Date对象的format方法用得场合是比较多的,《Microsoft.AJAX.Library.Essentials》有很好的参照


    8.3 String对象的扩展方法
stringobject

  以上看方法就大概知识提供什么样的功能了,这里就不多做解释了。

9.浏览器检测的问题

    最后,要谈谈浏览器检测的问题,检测相应的浏览器及版本号在JS中是一件不太容易的事情,因为浏览器版本多,品种多,以往是要靠以下方式来实现相应的检测:

ContractedBlock.gif ExpandedBlockStart.gif JS.checkBrowser
//检测浏览器型号
var sUserAgent = navigator.userAgent;
var fAppVersion = parseFloat(navigator.appVersion);
var isOpera = sUserAgent.indexOf("Opera") > -1;
var isIE = sUserAgent.indexOf("compatible") > -1 && sUserAgent.indexOf("MSIE") > -1 && !isOpera;
var isKHTML = sUserAgent.indexOf("KHTML") > -1 || sUserAgent.indexOf("Konqueror") > -1 || sUserAgent.indexOf("AppleWebKit") > -1;
var isMoz = sUserAgent.indexOf("Gecko") > -1 && !isKHTML;

//检测操作系统版本
var isWin = (navigator.platform == "Win32") || (navigator.platform == "Windows");
var isMac = (navigator.platform == "Mac68K") || (navigator.platform == "MacPPC") || (navigator.platform == "Macintosh");

var isWin2K = isWinXP = isWinVista = false;
if (isWin) {
    isWin2K
= sUserAgent.indexOf("Windows NT 5.0") > -1 || sUserAgent.indexOf("Windows 2000") > -1;
    isWinXP
= sUserAgent.indexOf("Windows NT 5.1") > -1 || sUserAgent.indexOf("Windows XP") > -1;
    isWinVista
= sUserAgent.indexOf("Windows NT 6.0") > -1 || sUserAgent.indexOf("Windows Vista") > -1;
}

  而现在在Microsoft.Ajax.Library中,通过Sys.Browser对象,可以很方便的检测出相关浏览器及版本号,且代码是兼容的。

var browser = string.format( " Your browser is  {0} {1} " ,Sys.Browser.name,Sys.Browser.version);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值