原生AJAX
一说起AJAX,可以大部分人都知道Asynchronous JavaScript and XML,就算不知道英文名,也知道中文名字,异步JavaScript和XML。相对于今天各种各样的类库,完美的Jquery和YUI封包,原来越多的人抛弃了原生的AJAX,原生AJAX众所周知的兼容性问题,N多的属性,N长的代码,让第一次接触的人望而却步,但是作为一个不习惯用不明白原理的东东的人,在这里写一些关于原生AJAX的白文。
Asynchronous JavaScript and XML(异步JavaScript和XML),简单的定义就是一种创建交互式网页应用的网页开发技术。简单的说它是多种技术的组合,目的就是让前台的数据交互变得更快捷,不用刷新页面就可以完成数据的更新。至于优缺点,就是能在不更新整个页面的前提下维护数据。这使得Web应用程序更为迅捷地回应用户动作,并避免了在网络上发送那些没有改变过的信息。利于用户体验,不会打断用户的操作,在不刷新页面的情况下更新内容,减小服务器压力也是它很硬性的一个优点;而缺点,除了倍受追捧的SEO问题,安全问题、前进后退(这个虽然可以用其他方法解决,但AJAX本身的机制还是没变)、破坏程序的异常机制以及对新兴手持设备支持不完美的问题都是它现存的一些缺点。人无完人,AJAX也是如此,我们并不能因为它有缺点而摒弃它。什么地方需要AJAX? 其实这是一个太宽泛的问题,各人各项目都有不同的用处,依我的经验与理解,AJAX应该用于小面积更新数据而不希望整个页面刷新的情况下使用。比如对用户名或者注册邮箱等数据判断、内容选项卡内容、弹出的登录注册窗口以及用户提交信息后的反馈信息等等。
至于具体的例子:这里引用的是别人的一个关于表单验证的例子,当用户输入完名字后,在表单外任何地方点一下(失去焦点),AJAX就迅速把用户输入的信息反馈到服务器端判断,并迅速返回一个信息告知用户输入的昵称是否可用。如此,我们需要一个前台的输入表单,首先我们需要一个HTML:
1 <form name="iform" method="post" action="#"> 2 <p> 3 <label for="nickname">用户名:</label> 4 <input placeholder="在这里输入用户名" id="nickname" name="nickname" type="text"> 5 <span id="tips"></span> 6 </p> 7 </form>
另外,我们还需要一个判断输入昵称是否存在的后端页面(本文以PHP为例,这部分不用细究):
1 ... 2 if(isset($_GET['entryname'])){ 3 $entryname=$_GET['entryname']; 4 }else{ 5 $entryname='DATA NULL'; 6 } 7 $sql=sprintf("select * from i_test_ajax where nickname='%s'",$entryname); 8 $res=$iajax->query($sql); 9 //sleep只是为了展示readState==1时的效果 10 sleep(1); 11 if(($res->num_rows)>0){ 12 echo "抱歉!此昵称已存在 :("; 13 }else{ 14 echo "恭喜!此昵称可注册 :)"; 15 } 16 ...
如此,万事俱备,只欠东风,剩下的就交给AJAX来处理了。 XMLHttpRequest,不得不提的一个对象,AJAX最核心也是最底层的对象。可悲哀的是,它是W3C的一个标准,但微软IE一直很自我(微软IE)。怎么办?当然是用一个方法和谐掉它们。微软IE支持ActiveXObject('Microsoft.XMLHTTP')对象,这样就简单了:
1 //兼容的XMLHttpRequest对象 2 IXHR: function(){ 3 if(window.ActiveXObject){ 4 XHR=new ActiveXObject('Microsoft.XMLHTTP'); 5 }else if(window.XMLHttpRequest){ 6 XHR=new XMLHttpRequest(); 7 }else{ 8 return null; 9 } 10 }
兼容的XMLHttpRequest对象实现了,接下来写一个简单的onblur事件,即当输入值后,表单失去焦点后开始判断并迅速回馈一个信息到前台。代码如下:
1 //触发焦点时执行 2 document.forms['iform'].nickname.onblur = function(){ 3 //输入的值 4 var val=document.forms['iform'].nickname.value; 5 //对用户名的判断 6 if(!/^[a-zA-Z0-9_]{3,16}$/.test(val)){ 7 alert('请输入3~16位由英文、数字、下划线组成的昵称!'); 8 return false; 9 } 10 //初始化一下XHR 11 iBase.IXHR(); 12 //原来需要新打开的判断页面用GET使用异步 13 XHR.open('GET','/demo/ajax/iajax20110306_query.php?entryname='+val,true); 14 //与readyState属性有关,当readyState改变时它才会触发 15 XHR.onreadystatechange=returnFun; 16 //异步处理完成后发送数据出去(比如某些需要在焦点事件后再执行的) 17 XHR.send(null); 18 }
解释一下AJAX部分的代码。iBase.IXHR(),初始化XHR,以保证XMLHttpRequest对象的兼容。接下来,通过以GET的方式,异步发送到/demo/ajax/iajax20110306_query.php页面进行验证。有人会问什么是GET,GET是从服务器上请求数据,GET方法就是把数据参数队列加到一个URL上,值和表单是一一对应的,比如本文的entryname=val。这个概念可能属于后台程序的范畴,不在此细说。然后,我们需要用到一个onreadystatechange事件属性,这个属性是用来存储函数(或函数名),每当readyState属性改变时,就会调用该函数,即本文中的returnFun;最后,我们还要发送一个数据到服务器,send属性一般用于数据交换,而本文只是一个简单的验证判断,所以,send一个空值。 基本的判断与数据发送完成了,接下来还剩一个关键的信息获取,即returnFun。先看代码:
1 function returnFun(){ 2 //当send()已调用,正在发送请求时,显示Loading... 3 if(XHR.readyState==1){ 4 iBase.Id('tips').innerHTML='Loding...'; 5 }else if(XHR.readyState==4){ 6 //当响应内容解析完成,可以调用时 7 //更缜密,再判断一下status是否成功 8 if(XHR.status==200){ 9 //responseText为返回的文本 10 iBase.Id('tips').innerHTML=XHR.responseText; 11 } 12 //使用完请销毁,避免内存泄露 13 XHR=null; 14 } 15 }
此函数是用来通过判断readyState及status状态也及时反馈给用户相应的提示信息。readyState有五种状态: 0 (未初始化): (XMLHttpRequest)对象已经创建,但还没有调用open()方法; 1 (载入):已经调用open() 方法,但尚未发送请求; 2 (载入完成): 请求已经发送完成; 3 (交互):可以接收到部分响应数据; 4 (完成):已经接收到了全部数据,并且连接已经关闭。 如此一来,你应该就能明白readyState的功能,而status实际是一种辅状态判断,只是status更多是服务器方的状态判断。关于status,由于它的状态有几十种,我只列出平时常用的几种: 100——客户必须继续发出请求 101——客户要求服务器根据请求转换HTTP协议版本 200——成功 201——提示知道新文件的URL 300——请求的资源可在多处得到 301——删除请求数据 404——没有发现文件、查询或URl 500——服务器产生内部错误 至此,一个简单的AJAX验证实例就完成了: 关于AJAX的基础介绍与实例就这么多,关键还是在于自己的实践与思考。其实这其中涉及知识并不复杂,若有后端程序的基础,学起AJAX会更加容易,关键是要想明白其中的逻辑关系。有兴趣的话,可以自己写一个不刷新页面加载新内容的AJAX,或者研究一下jQuery中关于AJAX的封装。