上次是最简单的原生JS实现AJAX效果。不过,那简单的步骤不能适应各种不同的浏览器,尤其是万恶的IE,尤其是低版本的IE浏览器。本期就来搞定各个浏览器,以及其他各项参数的设置。
一、服务端代码
服务端代码仍然使用.NET一般处理程序,这次的逻辑略有改动,通过QueryString获取一个key为type的参数,旨在接下来演示AJAX通过GET方式传参。此type属性预设值为“DATE“/”TIME“,如果是”DATE”,服务端就返回当前日期(年月日),否则返回当前时间(时分秒)。
public class TimeHandler : IHttpHandler { public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/plain"; string type = context.Request.QueryString["type"].ToUpper(); if(type == "DATE") { context.Response.Write(DateTime.Now.ToLongDateString()); } else { context.Response.Write(DateTime.Now.ToLongTimeString()); } } public bool IsReusable { get { return false; } } }
二、客户端JS代码
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title></title> <script> window.onload = function () { var btn = document.getElementById("btnTime"); btn.onclick = function () { ////1.声明异步对象 var xhr = false; //2.根据浏览器类型,创建异步对象 if (window.XMLHttpRequest) { xhr = new XMLHttpRequest(); } else { xhr = new ActiveXObject("Microsoft.XMLHTTP"); } //3.从下拉选项框中获取用户选中的选项 var type = document.getElementById("dType").value; //4.拼写url,把get请求传递的参数拼接到url后边 var url = "timehandler.ashx" + "?type=" + type; //5.打开异步对象,并设置参数 xhr.open("get", url, true); //6.设置setRequestHeader,不使用缓存数据 xhr.setRequestHeader("If-Modified-Since", "0"); //7.设置回调函数 xhr.onreadystatechange = function () { if (xhr.readyState == 4 && xhr.status == 200) { var h2 = document.getElementById("time"); h2.innerHTML = xhr.responseText; } } //4.发送异步请求 xhr.send(null); } } </script> </head> <body> <select id="dType"> <option value="DATE">年月日</option> <option value="TIME">时分秒</option> </select> <h2 id="time"></h2> <button id="btnTime">点击</button> </body> </html>
在客户端,用户通过选择select下拉框中的选项,然后点击btnTime按钮,获取服务器日期或时间。
与最简化的版本相比,变化点有以下几个
1.异步对象的创建。
不同的浏览器对于XMLHttpRequest对象的支持不同,这里主要指的是IE,尤其是老版本的IE,它们不支持该对象。IE老版本的浏览器支持的是MS自家的对象ActiveXObject,所以在创建的时候要先做下判断,以兼容老版本IE浏览器。
其中new ActiveXObject("Microsoft.XMLHTTP")时,传递的参数表示微软的xml语言解析器,用来解释xml语言的。就好像html文本下载到本地,浏览器会检查html的语法,解释html文本然后显示出来一样,不过不仅仅微软有。该也是有变化的,原因是微软在不同版本的浏览器中,对于该参数的解析也不同,所以也有人这么来创建异步对象
var xhr = false; var msXmlVers = ["MSXML2.XMLHttp.5.0", "MSXML2.XMLHttp.4.0", "MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp", "Microsoft.XMLHttp"]; if (window.XMLHttpRequest) { xhr = new XMLHttpRequest(); } else if (window.ActiveXObject) { for (var i = 0; i < msXmlVers.length; i++) { xhr = new ActiveXObject(msXmlVers[i]); if (xhr) { break; } } }
其中msXmlVers是个数组,该数组的各个项是不同的msxml解析版本。不过这么写的人貌似不多。
话又说回来了,现在谁还写原生的Javascript代码来做AJAX?所以这里我们了解就OK了,不求甚解了。
2.GET请求传参
AJAX对于Get请求和Post请求的传参方式是不同的。
Get请求仍然通过url传参,参数仍然以键值对的形式传递。语法:url?key1=val1&key2=val2&key3=val3..... ,与普通的get请求传出别无二致。
3.禁用客户端缓存
setRequestHeader是异步对象提供的一个重要的API,它是用来设置请求报文头的。
这里:xhr.setRequestHeader("If-Modified-Since", "0");是通过设置请求报文头的"If-Modified-Since",来达到禁用客户端缓存数据的目的。
至于为什么要禁用客户端缓存数据?
在http中Last-Modified 与If-Modified-Since 都是用于记录页面最后修改时间的 HTTP 头信息,注意,在这 Last-Modified 是由服务器往客户端发送的 HTTP 头,另一个 If-Modified-Since是由客户端往服务器发送的头,可以看到,再次请求本地存在的 cache 页面时,客户端会通过 If-Modified-Since 头将先前服务器端发过来的 Last-Modified 最后修改时间戳发送回去,这是为了让服务器端进行验证,通过这个时间戳判断客户端的页面是否是最新的,如果不是最新的,则返回新的内容,如果是最新的,则 返回 304 告诉客户端其本地 cache 的页面是最新的,于是客户端就可以直接从本地加载页面了,这样在网络上传输的数据就会大大减少,同时也减轻了服务器的负担。而且在一些ajax应用中,要求获取的数据永远是最新的,而不是读取位于缓存中的数据,做这样的设置是非常有必要的。
那么除了这种方法禁用缓存数据以外,还有一个种方法,就是在请求的url上做手脚。比如:var url = "timehandler.ashx" + "?timestamp=" + new Date().getTime();