文章教程

18.2AJAX与数据交互

9/17/2020 9:31:19 PM 人评论 次浏览

18.2 AJAX与数据交互

AJAX是运行在浏览器端的技术,它在浏览器端和服务器端之间使用异步技术传输数据。但完整的AJAX的应用还需要服务器端的组件,毕竟浏览器端所有的请求将要由服务器端处理。浏览器端仅仅是通过JavaScript发出请求,并等待服务器的响应,最后处理服务器端传来的数据。服务器端可以使用任何一种语言实现应用,本书中这种语言只能是PHP。本节就向读者介绍AJAX和PHP在Web开发中的结合应用。

18.2.1 创建XMLHttpRequest对象

XMLHttpRequest对象是AJAX的关键所在,也是使用XMLHttpRequest对象是实现AJAX技术的第一步。XMLHttpRequest是一个JavaScript对象,创建该对象很简单,代码如下。


     01 <script language="javascript">
     02     var xmlHttp = new XMLHttpRequest();
     03 </script>

【代码解析】这段代码创建了一个XMLHttpRequest对象,并将其赋给JavaScript变量xmlHttp,该变量即代表了XMLHttpRequest对象。但是,由于不同的浏览器使用不同的方法创建XMLHttpRequest对象,例如,IE就使用ActiveXObject。如下JavaScript代码解决了这个问题。


     01 var xmlHttp=null
     02 if (window.xmlHttpRequest)
     03 {
     04     xmlHttp=new xmlHttpRequest()
     05 }
     06 else if (window.ActiveXObject)
     07 {
     08     xmlHttp=new ActiveXObject("Microsoft.xmlHTTP")
     09 }

【代码解析】代码第01行定义了一个变量xmlHttp,将来作为XMLHttpRequest对象来使用,将其赋值为null。然后判断window.xmlHttpRequest对象是否存在,如果存在就创建该对象,否则就创建ActiveXObject对象,如代码第08行所示。这里的参数Microsoft.xmlHTTP是ActiveX对象的ID。

然而,这样创建XMLHttpRequest请求在某些情况下仍然会有问题。因为ActiveXObject方法调用所使用的参数可能会有所不同,除了Microsoft.xmlHTTP,对于更新版本的IE浏览器,该参数就是Msxml2.XMLHTTP。另外,如果试图在浏览器端创建一个不存在的ActiveX对象,应该抛出一个异常。所以,代码18-1是更完整的创建XMLHttpRequest对象的JavaScript程序。

代码18-1 完整的创建XMLHttpRequest对象的JavaScript程序18-1.js


     01 function GetXmlHttpRequest()
     02 {
     03     var xmlHttp=null;
     04     try
     05     {
     06         xmlHttp = new XMLHttpRequest();                      //
对于Firefox
等浏览器
     07     }
     08     catch(e)
     09     {
     10         try
     11         {
     12             xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");   //
对于IE
浏览器
     13         }
     14         catch (e)
     15         {
     16             try
     17             {
     18                 xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
     19             }
     20             catch(e)
     21             {
     22                 xmlHttp = false;
     23             }            
     24         }
     25     }
     26 
     27 return xmlHttp;
     28 }

【代码解析】代码将创建XMLHttpRequest对象的功能封装在一个函数之内。创建XMLHttpRequest对象的步骤如下所述。

(1)建立一个变量xmlHttp来引用即将创建的XMLHttpRequest对象,如代码第03行所示。

(2)尝试在非IE浏览器端创建该对象,如代码第06行所示。如果成功,则不再执行后续代码,变量xmlHttp即为所创建的XMLHttpRequest对象。

(3)如果上步创建失败,则尝试在IE浏览器中使用Msxml2.XMLHTTP创建XMLHttpRequest对象;如果成功,则不再执行后续代码,变量xmlHttp即为所创建的XMLHttpRequest对象。

(4)如果上步失败,再尝试使用Microsoft.XMLHTTP创建该对象;如果成功,变量xmlHttp即为所创建的XMLHttpRequest对象。

(5)如果以上步骤都失败,则该对象赋值为false,表示创建XMLHttpRequest对象失败。

18.2.2 发送异步请求

18.2.1小节向读者介绍了实现AJAX应用的关键一步。之所以说它是关键一步,是因为,正是这个“伟大的”XMLHttpRequest对象将要向Web服务器发出请求,正是这一步实现了通过JavaScript和Web应用程序交互,而不是用户提交给Web服务器的那个HTML表单。

那么,到底如何使用XMLHttpRequest对象向服务器发出请求呢?首先就是要创建一个JavaScript函数,该函数由Web页面调用,比如用户输入数据或者在下拉列表中做了选择时,这个JavaScript函数内将使用XMLHttpRequest对象向服务器发出请求。在实现使用JavaScript向服务器发出请求之前,读者还需要进一步了解XMLHttpRequest对象的一些方法,它们在AJAX应用中发挥着至关重要的作用,读者有必要了解每一个方法,这些方法介绍如下。

·open()方法,基本用法是open(method,url[,async])。open方法会使用method参数所指定的方式(GET或POST)打开(或设置)一个到参数url所指定的连接。可选参数async可以将请求设置为异步或同步,如果该参数值为true,则表示异步,反之为同步,默认值为true,即发起异步请求。该方法还有两个可选参数,因为在本书的实例中不会涉及,这里不再赘述。

·setRequestHeader()方法,用法是setRequestHeader(label,value)。它的作用就是在请求报头中增加一个“标签-值”对。

·send()方法,用法是send(content)。“伟大的”XMLHttpRequest对象将调用同样“伟大的”send()方法向服务器发出请求,send()方法是XMLHttpRequest对象的灵魂所在,就是在这个方法中,JavaScript将请求和数据向服务器发送出去,一切“生动的”应用从这个方法开始。

·getAllResponseHeaders()方法,用法是getAllResponseHeaders(),它获取服务器的所有HTTP响应报头,并将其作为一个字符串返回。这个字符串包含的信息有活动状态的超时时间、内容类型、和服务器有关的信息和日期。

·getReponseHeader()方法,用法是getReponseHeader(label),它获取一个有参数label指定的HTTP响应报头。

·abort()方法,用法是abort(),它用来中止当前的请求。

在了解了XMLHttpRequest对象之后,还有必要认识一下该对象的属性,它在AJAX应用中同样是很重要的。表18-1列举了XMLHttpRequest对象的属性及其含义描述。

表18-1 XMLHttpRequest对象的属性及其含义

在熟悉XMLHttpRequest对象的方法和属性之后,接下来就可以实现使用XMLHttpRequest对象向服务器发出请求的JavaScript函数了。该JavaScript函数假定某个Web页面的Form表单中有个名叫name的文本框,该函数获取该文本框中的数据,并将该数据提交一个名叫getUserName.php的服务器程序,这个程序将处理浏览器提交的数据。因为这里只是将讲解AJAX如何通过JavaScript向服务发出请求,所以并没有实现服务器端的程序,读者在这里需要重点了解XMLHttpReques对象方法的使用。代码18-2为该JavaScript函数的具体实现代码。

代码18-2 发出异步请求的JavaScript程序18-2.js


     01 function sendRequest()
     02 {
     03     //
获取页面表单的文本框name
的值
     04     var user_name = document.getElementById("name").value;
     05 
     06     if((user_name == null) || (user_name == ""))
     07         return;
     08     
     09     xmlHttp = GetXmlHttpRequest();
     10     if(xmlHttp == null)
     11     {
     12         alert("
浏览器不支持XmlHttpRequest
!");
     13         return;
     14     } 
     15 
     16     var url = "getUserName.php";       //
构建请求的URL
地址
     17     url = url + "?name=" + user_name;
     18     
     19     xmlHttp.open("GET", url, true);    //
使用GET
方法打开一个到url
的连接,为发出请求做准备
     20     //
设置一个函数,当服务器处理完请求后调用,该函数名为updatePage
     21     xmlHttp.onreadystatechange = updatePage;
     22     xmlHttp.send(null);                //
发送请求
     23 }

【代码解析】这段JavaScript函数完成向服务器发出请求的功能,其中的代码意义都很明确,并没有晦涩难懂的地方,这里做一些简要的解释。代码第04行使用基本的JavaScript代码获取表单文本框元素name的值。在该值有效的情况下,调用18.3.1小节介绍的函数GetXmlHttpRequest()完成XmlHttpRequest对象的创建。如果XmlHttpRequest对象创建成功,则构建一个url地址,这个地址由服务器端处理程序及其需要的参数拼接而成,该地址就是将来要向服务器发起请求的地址。

接着,在代码第19行调用XmlHttpRequest对象的open方法,打开此前建立的url地址,使用GET方法传送数据,并将请求设置为异步方式(open()方法的第3个参数为ture,表示异步请求)。第19行代码中是第1次使用XmlHttpRequest对象。

代码第21行使用了XmlHttpRequest对象的onreadystatechange属性,该属性的作用就是告诉服务器在请求处理完成之后做什么。因为是异步请求,在JavaScript发出请求后并没有等待服务器的响应,所以当服务器完成请求处理,向浏览器发出响应时,应该通知JavaScript,这就是onreadystatechange属性存在的意义。在这个示例中,当服务器完成请求处理,将触发一个名叫updatePage()的JavaScript函数。

代码第22行中XmlHttpRequest对象调用方法send()将请求向服务器发出。

相信读者目前已经意识到AJAX并不是那么神秘,因为AJAX本身没有什么复杂的内容,一切都是按流程化的步骤进行。AJAX所实现的提交表单的办法和传统的方法使用的是相同的技术,不同之处是AJAX通过JavaScript向服务器发出请求并由JavaScript处理响应,还有就是在整个请求和响应过程中页面一直保持着。

在本小节最后总结一下AJAX应用的基本流程,以使读者对AJAX请求部分有更清楚的理解,总结如下所述。

·创建XmlHttpRequest对象。

·在JavaScript函数中获取表单数据。

·建立要连接的URL地址。

·打开到该URL所在服务器的连接。

·设置服务器处理完请求后需要调用的函数。

·发送请求。

18.2.3 编写回调函数

18.2.2小节示例代码的第21行所指定的服务器处理完请求之后所要调用的函数,即所谓的回调函数,JavaScript将在这个函数中完成对服务器返回响应的处理。

XmlHttpRequest对象的readyState属性表示了请求/响应过程中的不同状态。当该属性值为4时,表示响应加载完毕。XmlHttpRequest对象的另一个属性responseText存放了服务器文本格式的响应,也就是说,服务器将请求的处理结果填充到XmlHttpRequest对象的responseText属性中。知道了这两点,完成回调函数就顺理成章、水到渠成了。代码18-3就是处理服务器响应的JavaScript函数的一个实现。

代码18-3 处理服务器响应的JavaScript程序18-3.js


     01 function updatePage()
     02 {
     03     if(xmlHttp.readyState == 4)
     04     {
     05         var response = xmlHttp.responseText;
     06         document.getElementById("userInfo").value = response;
     07     }
     08 }

【代码解析】这段处理服务器响应的代码看起来要比发出请求的JavaScript代码简单。该函数等待服务器的调用,当服务器处理完请求,就会调用该函数。代码第03行判断XmlHttpRequest对象的readyState属性的值是否为4,如果为4,则通过XmlHttpRequest对象的responseText获取服务器的响应数据,如代码第05行所示。然后通过JavaScript代码将这个服务器响应结果显示到Web页面中,如代码第06行所示。AJAX正是在这里实现了页面没有刷新,但页面内容却被更新的效果。

18.2.4 完整实例

有了以上3个小节的基础知识,读者已经清楚了AJAX内部机制,完全可以在具体的应用中实践AJAX了。这小节将通过一个完整的实例,向读者展示AJAX与PHP程序的具体应用。

这个实例实现的功能是,当用户在Web页面的下拉列表框中选择某个省的名称时,会在页面上显示该省的省会名称,而此时页面并不刷新。省会名称将由服务器端传送至浏览器端。这个完整实例将包含以下3个部分。

·HTML页面,包含下拉列表框和要显示省会名称的位置。

·JavaScript程序,实现发送请求和处理响应。

·服务端的PHP程序,用来接收浏览器的请求,向浏览器传送结果数据。

通常JavaScript程序可以直接写在HTML页面当中,也可以将JavaScript程序单独写在.js文件中,然后在HTML中引用。本例将采用前一种做法。代码18-4就是该HTML页面和JavaScript程序的完整代码。

代码18-4 选择数据HTML页面18-4.html


     01 <html>
     02 <head>
     03 <title>ajax
应用实例</title>
     04 
     05 <script language="javascript">
     06 var xmlHttp = null;
     07 
     08 function GetXmlHttpRequest()
     09 {
     10     var xmlHttp=null;
     11     try                                                   //
创建XMLHttpRequest
对象
     12     {
     13         xmlHttp = new XMLHttpRequest();
     14     }
     15     catch(e)
     16     {
     17         try
     18         {
     19             xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
     20         }
     21         catch (e)
     22         {
     23             try
     24             {
     25                 xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
     26             }
     27             catch(e)
     28             {
     29                 xmlHttp = false;
     30             }            
     31         }
     32     }
     33 
     34 return xmlHttp;                                         //
返回XMLHttpRequest
对象
     35 }
     36 
     37 function sendRequest()                                  //
发送异步请求
     38 {
     39     var prov_name = document.getElementById("province").value;
     40 
     41     if((prov_name == null) || (prov_name == ""))
     42         return;
     43     
     44     xmlHttp = GetXmlHttpRequest();
     45     if(xmlHttp == null)
     46     {
     47         alert("
浏览器不支持XmlHttpRequest
!");
     48         return;
     49     } 
     50 
     51     var url = "18-5.php";
     52     url = url + "?prov=" + prov_name;
     53 
     54     xmlHttp.open("GET", url, true);
     55     xmlHttp.onreadystatechange = updatePage;
     56     xmlHttp.send(null);
     57 }
     58 
     59 function updatePage()                                   //
处理服务器响应
     60 {
     61     if(xmlHttp.readyState == 4 && xmlHttp.status == 200)
     62     {
     63         var response = xmlHttp.responseText;
     64         document.getElementById("city").innerHTML = response;
     65     }
     66 }
     67 </script>
     68 
     69 <head>
     70 
     71 <body>
     72 <h3>
请选择一个省(自治区):</h3>
     73 
     74 <form action="18-5.php">
     75     <div>
     76     <select id="province" onchange="sendRequest()">
     77         <option value="">
请选择一个省(自治区)</option>
     78         <option value="ah">
安徽</option>
     79         <option value="fj">
福建</option>
     80         <option value="gs">
甘肃</option>
     81         <option value="gd">
广东</option>
     82         <option value="gx">
广西</option>
     83         <option value="gz">
贵州</option>
     84         <option value="hn">
海南</option>
     85         <option value="hb">
河北</option>
     86         <option value="hh">
河南</option>
     87         <option value="hl">
黑龙江</option>
     88     </select>
     89     </div>
     90 </form>
     91 
     92 <div id="city">
     93 </div>
     94 
     95 </body>
     96 </html>

【代码解析】代码的JavaScript部分就是前面3个小节所讲的AJAX实现步骤的JavaScript函数,这里就不再赘述其功能。代码的HTML部分是在一个表单中加入下拉列表框供用户选择,选择后就会向服务器提交数据,服务器处理完成后回调用updatePage()函数,将结果显示在该HTML页面的ID为“city”的div中,如代码第92行所示。

下面完成服务器端的PHP程序,该程序将获取浏览器端由JavaScript提交的数据,即省份名称,然后在一个数组内找到该省份匹配的省会名称,将该名称返回至浏览器端。代码18-5是完整的服务器端PHP程序。

代码18-5 服务器端处理数据的PHP程序18-5.php


     01 <?php
     02 $city_arr = array(
     03 "ah"=>"
合肥",
     04 "fj"=>"
福州",
     05 "gs"=>"
兰州",
     06 "gd"=>"
广州",
     07 "gx"=>"
南宁",
     08 "gz"=>"
贵阳",
     09 "hn"=>"
海口",
     10 "hb"=>"
石家庄",
     11 "hh"=>"
郑州",
     12 "hl"=>"
哈尔滨"
     13 );
     14 
     15 if(empty($_GET['prov']))
     16 {
     17     echo iconv("GB2312","UTF-8",'<font color="red">
您没有选择省(自治区)</font>');
     18 }
     19 else
     20 {
     21     $prov = $_GET['prov'];
     22     $city = $city_arr[$prov];
     23     echo iconv("GB2312","UTF-8",'
所选省(自治区)省会(首府)为:'.$city);
     24 }
     25 ?>

图18-2 AJAX执行效果图

【代码解析】这是一个很简单的PHP程序,首先定义一个数组用来存储省会名称,然后根据浏览器传入的数据从该数组中取得所对应的省会名称,最后将该数据输出。这里需要解释一下代码第23行,使用了PHP的iconv函数做字符编码转换,如果程序18-5.php使用GB2312编码保存,因为存在汉字字符,在使用JavaScript回调函数时会出现异常,所以这里将编码GB2312转换成UTF-8,以便JavaScript的XMLHttpRequest对象能够正确显示数据。如果程序18-5.php使用了UTF-8编码保存,则不存在这个问题。图18-2是这个实例执行的一个效果图。

本小节实例代码最后向浏览器端响应的是一个字符串结果,并不是XML。这样做只是为了更便于读者理解AJAX的工作原理及使用方法。事实上,服务器的响应是XML才更符合AJAX的本质。如果浏览器端得到的响应是XML,那么在回调函数中就要实现对XML的处理,最终完成页面内容的更新。

教程类别