JavaScript And Ajax(理解 Ajax)

       开发人员使用 js 代码的另一个主要原因是避免回传。考虑 TreeView 控件,用户能随意展开或收合节点。展开节点时,TreeView 通过 JavaScript 从服务器获取子节点的信息并插入新节点。没有 JavaScript,页面就只能回传以重建 TreeView。用户会看到略微缓慢的延迟,页面甚至可能重新滚动回到开始,在服务器端需要浪费大量时间序列化和反序列化每个回传的视图状态信息。

       如何避免这种额外的负载以及如何使用一点 js 创建更平滑、更简单的页面?自包容的 js 作为独立任务实现,不需要和页面模型的其他部分交互,例如一个弹出信息或者滚动状态显示。然而,如果希望创建像 TreeView 那种真正动态的页面,会发生什么呢?

       它调用服务器端的方法,等候响应,动态的插入新信息,而这一切都不触发页面回传。要设计这样的解决方案,你需要让客户端脚本和服务器端代码通信。

 

Ajax 简介

       Ajax(Asynchronous JavaScript and XML),它是一种具有特定特征的 JavaScript 程序。Ajax 风格的页面在后台与服务器通信,请求额外的信息。客户端代码获得这些信息后,执行额外的动作。

       例如,使用 Ajax 技术可以抓取实时的股票报价并刷新页面的一个区域而不需要触发回传。客户端和服务器端的通信是异步的,因此客户端不会被打扰。具有更好的响应性以及平滑的浏览体验,这些都不需要刷新。

       Ajax 的页面编程可能很复杂,这不是因为 JavaScript 技术特别难(它们并不难),而是因为有时需要复杂的变通方案来确保浏览器的兼容性。理想下,ASP.NET 程序员根本不需要操心编写 Ajax 风格的页面。相反,应该使用服务器端的高级框架,它们可以注入你需要的 js 代码但这一目标目前进展很慢,毕竟,微软需要时间仔细考虑把这些客户端功能整合到 ASP.NET 服务器端模型的各种方案。

 

XMLHttpRequest 对象

       XMLHttpRequest 对象是 Ajax 的基石。XMLHttpRequest 令人不可思议的有用,又难以置信的简单。它能以文本的形式向服务器发送异步请求并以文本的形式获得结果,而请求什么、返回什么则由你来决定

       尽管现代浏览器对 XMLHttpRequest 对象有广泛的支持,但是它们对如何访问这个对象还是有细微差别的。IE7、Firefox、Safari、Opera 将 XMLHttpRequest 对象作为本地 JavaScript 对象实现的。而在 IE7 之前的浏览器中,XMLHttpRequest 对象是作为 ActiveX 对象实现的。

       因为这些差别,js 代码在创建 XMLHttpRequest 对象的实例时,必须要有足够的智能来采用正确的方式。这是微软为客户端回调功能实现这一任务的 js 代码:

var xmlRequest;
try
{
    xmlRequest = new XMLHttpRequest();
} 
catch (err)
{
    xmlRequest = new ActiveXObject("Microsoft.XMLHTTP");
}

 

1. 发送请求

       可以使用 XMLHttpRequest 的两个主要方法来发送请求:open()send()

       open() 方法建立调用,定义要发送到服务器的请求。它有两个必须的参数:HTTP 命令的类型(GET、POST、PUT)和 URL。像下面这样:

xmlRequest.open("GET", "myUrl");

       此外,可以提供第三个参数表明请求是否要异步执行;还有两个可选参数指定用于验证的用户名和密码。你不可能使用用户名和密码参数,这些信息不能够安全的硬编码到 js 代码中,客户端代码从来都不是安全的场所发出的请求默认情况就是异步执行的,毫无理由改变这一行为

 

       send() 方法启动请求。请求是异步的话,它会立刻返回

xmlRequest.send(null);

       可选择的,send() 方法接受一个字符串参数。可用该参数提供随请求一起发送的额外信息,就像那些随 POST 一起发送的值

       IE 浏览器可以忽略 send() 方法的参数,Firefox 则必须提供一个 null 引用,否则回调行为将不规律。编写客户端脚本时跨浏览器兼容的问题将始终伴随着你。

 

2. 处理响应

       使用 onreadystatechange 属性附加事件处理程序来处理响应。这个属性指向一个 js 函数,该函数在请求结束获得数据后被调用。

xmlRequest.onreadystatechange = UpdatePage;

       你要在调用 send() 之前附加事件处理程序当响应从服务器返回且函数被触发时,可以用 responseTextresponseXML 属性从 xmlRequest 对象析取需要的信息

       responseText 属性把所有内容作为一个字符串返回。responseXML 属性把内容作为树的节点对象返回。

       (虽然 Ajax 暗示 XML 内容,但仍可以返回其他内容,例如,纯文本。如果服务器返回一段数据,没有理由一定要包装在完整的 XML 文档里。例如 Jason 数据格式就是一个很好的纯文本数据选择。)

 

 

Ajax 示例

       在 ASP.NET 里构建 Ajax 风格的页面,需要如下两个元素:

  • 启用 Ajax 的网页。它包含通过 XMLHttpRequest 对象送出请求的客户端代码。
  • 另一个页面或资源。它处理第一个页面的请求并发送适当的响应。

       第一个元素显然是一个 .aspx 网页。第二个元素可以是另一个 .aspx网页,或者一个自定义的 HTTP 处理程序。HTTP 处理程序是更轻量的选项,因为它不使用完整的页面模型

 

       下面的例子以 HTTP 处理程序实现服务器端的功能。HTTP 处理程序 通过查询字符串接收信息,然后返回两段信息(两个参数的和以及 Web 服务器的当前时间)。

       下面是 HTTP 处理程序的完整代码:

public class CaculatorCallbackHandler : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        HttpResponse response = context.Response;
 
        response.ContentType = "text/plain";
 
 
        float value1, value2;
        if (Single.TryParse(context.Request.QueryString["value1"], out value1) &&
            Single.TryParse(context.Request.QueryString["value2"], out value2))
        {
            response.Write(value1 + value2);
            response.Write(",");
            response.Write(DateTime.Now.ToLongTimeString());
 
        }
        else
        {
            response.Write("-");
        }
    }
 
    public bool IsReusable
    {
        get
        {
            return true;
        }
    }
}

       (这个 HTTP 处理程序简单的不切实际。当服务器端代码要做客户端代码不能完成的事时,这种模式才会显得有意义。如查找服务器端资源中的信息、使用敏感信息、或者使用只在 .NET Framework 中才有的类执行复杂操作。)

 

       有了 HTTP 处理程序后,随时可以使用 XMLHttpRequest 对象调用它。下面是页面的基本轮廓,没有包括 js 代码。这个页面用两种方法插入客户端的 js 代码。首先,<body> 标签里的 onload 事件启动 CreateXMLHttpRequest() 函数;其次,两个文本框使用 onkeyup 事件触发 CallServerForUpdate() 函数。

<body onload="CreateXMLHttpRequest();">
    <form id="form1" runat="server">
    <div>
        <table style="width: 296px">
            <tr>
                <td>
                    <img src="lava_lamp.gif" alt="Animated Lamp" />
                </td>
                <td>
                    This animated GIF won't pause, demonstarting that your page isn't posting back to
                    the server.
                    <br />
                    <br />
                    Value 1:
                    <asp:TextBox ID="txt1" runat="server" onkeyup="CallServerForUpdate();" /><br />
                    Value 2:
                    <asp:TextBox ID="txt2" runat="server" onkeyup="CallServerForUpdate();" /><br />
                    <br />
                    <asp:Label ID="lblResponse" runat="server" Text="" />
                </td>
            </tr>
        </table>
    </div>
    </form>
</body>

 

       CreateXMLHttpRequest() 函数负责创建 XMLHttpRequest 对象:

var xmlRequest;
function CreateXMLHttpRequest() {
    try {
        xmlRequest = new XMLHttpRequest();
    }
    catch (err) {
        xmlRequest = new ActiveXObject("Microsoft.XMLHTTP");
    }
}

 

       CallServerForUpdate() 函数找到文本框对象,使用它们的值构建指向 HTTP 处理程序的 URL:

function CallServerForUpdate() {
    var txt1 = document.getElementById("txt1");
    var txt2 = document.getElementById("txt2");
    var url = "CaculatorCallbackHandler.ashx?value1=" +
        txt1.value + "&value2=" + txt2.value;
    xmlRequest.open("GET", url);
    xmlRequest.onreadystatechange = ApplyUpdate;
    xmlRequest.send(null);
}

 

       ApplyUpdate() 函数得到响应时执行,从文本中解析出信息显示在标签中:

function ApplyUpdate() {
    if (xmlRequest.readyState == 4) {
        if (xmlRequest.status == 200) {
            var lbl = document.getElementById("lblResponse");
            var response = xmlRequest.responseText;
            if (response == "-") {
                lbl.innerHTML = "You've entered invalid numbers.";
            } else {
                var responseString = response.split(",");
                lbl.innerHTML = "The server returned the sum: " +
                    responseString[0] + " at " + responseString[1];
            }
        }
    }
}

 

       现在运行页面进行测试,效果如下:

image

posted on 2012-12-20 15:56  SkySoot  阅读(496)  评论(0编辑  收藏  举报

导航