第17章 PHP与AJAX
异步JavaScript和XML(Asynchronous JavaScript and XML,AJAX)无疑是最流行的Web技术之一。使用它不仅能做出绚丽多彩的效果,而且能在一定程度上提高网站负载能力,还能做出很好的用户体验。本章首先讲解什么是AJAX,以及它的原理和实现流程,最后结合PHP做一个简单的用户名验证程序。
17.1 什么是AJAX
AJAX全称为“Asynchronous JavaScript and XML”(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术,使浏览器可以为用户提供更为自然的浏览体验。AJAX不是一种技术,它实际上是几种技术,每种技术都有其独特之处,合在一起就成了一个功能强大的新技术。AJAX包括:
- XHTML和CSS。
- 使用文档对象模型(Document Object Model)做动态显示和交互。
- 使用XML和XSLT做数据交互和操作。
- 使用XMLHttpRequest进行异步数据接收。
- 使用JavaScript将它们绑定在一起。
AJAX提供与服务器异步通信的能力,从而使用户从请求/响应的循环中解脱出来。借助于AJAX,可以在用户单击按钮时,使用JavaScript和DHTML立即更新UI,并向服务器发出异步请求,以执行更新或查询数据库。当请求返回时,就可以使用JavaScript和CSS来相应地更新UI,而不是刷新整个页面。最重要的是,用户甚至不知道浏览器正在与服务器通信:Web站点看起来是即时响应的。
17.2 AJAX的实现原理和工作流程
AJAX的工作原理相当于在用户和服务器之间加了—个中间层,使用户操作与服务器响应异步化。并不是所有的用户请求都提交给服务器,像—些数据验证和数据处理等都交给AJAX引擎自己来做,只有确定需要从服务器读取新数据时再由AJAX引擎代为向服务器提交请求。可以用图17.1表示这之间的关系。
图17.1 AJAX网页应用模型
从图17.1可以看出,客户端的静态页面向服务器端发送请求后,就可以通过AJAX引擎直接得到从服务器端传过来的数据。
AJAX应用程序的优势在于:
- 通过异步模式,提升了用户体验。
- 优化了浏览器和服务器之间的传输,减少不必要的数据往返,减少了带宽占用。
- AJAX引擎在客户端运行,承担了一部分本来由服务器承担的工作,从而减少了服务器负载。
虽然使用AJAX有很多的好处,但是它也有局限性。一般有如下几点:
- 不能实时请求和响应服务器数据。
- 不支持浏览器回退功能。
- 不能提交多媒体数据,比如图片,文件等。
所以,在使用这项技术的时候需要了解它的特性,做到知之用之。
17.3 AJAX应用
AJAX是运行在浏览器端的技术,它在浏览器端和服务器端之间使用异步技术传输数据。但完整的AJAX应用还需要服务器端的支持,因为浏览器端发出的请求要由服务器端处理并返回结果。服务器端的程序可以使用任何一种语言实现应用,在本书中使用的是PHP。本节介绍AJAX和PHP在Web开发中的结合应用。
17.3.1 如何建立远程连接对象
AJAX的核心是XMLHttpRequest对象,也就是远程连接对象。它是一套可以在JavaScript、VBScript、JScript等脚本语言中通过HTTP协议传送或者接收XML及其他数据的一套API。XMLHttpRequest最大的用处是可以更新网页的部分内容而不需要刷新整个页面。但是在不同的浏览器建立这个对象的方式有所不同。
在Firefox和IE7、IE8中可以用如下方式建立该对象:
<script language="javascript"> var xmlHttp = new XMLHttpRequest(); </script>
在IE6中则只能用如下方式:
<script language="javascript"> var xmlHttp = new ActiveXObject("Microsoft.xmlHTTP") </script>
原因在于早先的IE浏览器版本只支持采用ActiveX对象这种方式建立XMLHttpRequest对象。所以要兼容主流的浏览器方式的话,就得结合以上两种方式。代码如下:
var xmlHttp=null if (window.xmlHttpRequest) { xmlHttp = new xmlHttpRequest() } else if (window.ActiveXObject) { xmlHttp = new ActiveXObject("Microsoft.xmlHTTP") }
以上代码首先定义了一个变量xmlHttp,用来存储XMLHttpRequest对象,先将其赋值为null。然后判断window.xmlHttpRequest对象是否存在,如果存在就创建该对象;否则,就创建XMLHttpRequest的ActiveXObject对象。其中Microsoft.xmlHTTP是XMLHttpRequest对象(ActiveX控件)的ID。
但是由于IE浏览器版本的关系,有的IE浏览器还支持更高版本的XMLHttpRequest控件,所以更完整地创建一个远程连接对象可以使用代码17-1。
代码17-1 建立远程连接对象
function getXmlHttpRequest() { var xmlHttp=null; //创建一个变量 try { xmlHttp = new XMLHttpRequest(); //对于Firefox等浏览器 } catch(e) { try { xmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); //对于IE浏览器 } catch (e) { try { xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch(e) { xmlHttp = false; } } } return xmlHttp; }
这段代码将创建XMLHttpRequest对象的功能封装在一个函数之内。下面对该函数的操作步骤加以说明。
(1)首先建立一个变量xmlHttp来存储XMLHttpRequest对象,如代码第3行所示。
(2)尝试在非IE浏览器端创建该对象,如代码第6行所示。如果成功,则不再执行后续代码,变量xmlHttp即为所创建的XMLHttpRequest对象。
(3)如果上步创建失败,则尝试在IE浏览器中使用Msxml2.XMLHTTP创建XMLHttpRequest 对象。如果成功,则不再执行后续代码,变量xmlHttp即为所创建的XMLHttpRequest 对象。
(4)如果上步失败,再尝试使用Microsoft.XMLHTTP创建该对象。如果成功,变量xmlHttp即为所创建的XMLHttpRequest 对象。
(5)如果以上步骤都失败,则该对象赋值为false,表示创建XMLHttpRequest对象失败。
17.3.2 异步发送请求
异步发送请求是AJAX技术中最重要的环节,也是它区别于传统请求的不同之处。正是这一步实现了通过JavaScript和Web应用程序的交互,而不是像用户单击提交按钮后将提交Web客户端的整个HTML表单。在做这一步之前,有必要先对XMLHttpRequest对象的每一个属性方法有一个初步的了解。它的属性和方法分别如表17.1和表17.2所示。
表17.1 XMLHttpRequest对象的属性
表17.2 XMLHttpRequest对象的方法
在熟悉XMLHttpRequest对象的方法和属性之后,接下来,就可以实现使用XMLHttpRequest对象向服务器发出请求的JavaScript函数了。下面就以一个经典的AJAX发送函数作为示例来讲解如何异步发送请求,该JavaScript函数的具体实现如代码17-2所示。
代码17-2 发出异步请求的JavaScript程序
function sendRequest(url, call_back, data) { xmlHttp.onreadystatechange = call_back; var data = data || ""; if(data != "") { xmlHttp.open("POST", url, true); //使用POST方法打开一个到url的连接, 为发出请求做准备 //以下为POST方式提交数据,所需要的header xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xmlHttp.setRequestHeader("Content-length", data.length); xmlHttp.setRequestHeader("Connection", "close"); } else { xmlHttp.open("GET", url, true); //使用GET方法打开一个到url的连接, 为发出请求做准备 } xmlHttp.send(data); //发送请求 }
这段JavaScript函数完成向服务器发出请求的功能,其中的代码意义都很明确,并没有晦涩难懂的地方,因此这里只做一些简要的解释。
首先在代码第3行使用了XmlHttpRequest对象的onreadystatechange属性,该属性的作用是告诉服务器在请求处理完成之后做什么。因为是异步请求,在JavaScript发出请求后并没有等待服务器的响应,所以当服务器完成请求处理,向浏览器发出响应时,应该通知JavaScript,这就是onreadystatechange属性存在的意义。在这个示例中,当服务器完成请求处理时,将触发一个名叫call_back()的JavaScript入参函数。
接着在代码第4行,如果没有传入data参数,则data为空,否则就是传入的data的值。如果data存在,则调用XmlHttpRequest对象的open方法,打开此前建立的url地址,使用POST方法传送数据,并将请求设置为异步方式(open()方法的第3个参数为true,表示异步请求)。如果data也是调用该方法,只是第一个参数改为GET,表示使用GET方式传送数据。
注意 在使用POST方式提交数据时,不但需要将open方法的第一个参数设置为POST,还需要使用setRequestHeader()函数发送特定的header,如代码中所示。
最后在代码第18行,XmlHttpRequest对象调用方法send()将请求向服务器发出。相信读者目前已经意识到AJAX并不是那么神秘,因为AJAX本身没有什么复杂的内容,一切都是按流程化的步骤进行。AJAX所实现的提交表单的办法和传统的方法使用的是相同的技术;不同之处是AJAX通过JavaScript向服务器发出请求并由JavaScript处理响应,还有就是在整个请求和响应过程中,页面一直保持着。
在这里总结一下AJAX应用的基本流程,以使读者对AJAX请求部分有更清楚的理解。总结如下所示。
- 创建XmlHttpRequest对象。
- 在JavaScript函数中获取表单数据。
- 建立要连接的URL地址。
- 打开到该URL所在服务器的连接。
- 设置服务器处理完请求后需要调用的函数。
- 发送请求。
17.3.3 回调函数的应用
17.3.2节中已经介绍了如何使用AJAX发送一个请求,那么之后服务器端便会收到这个请求并且会做一个相应的操作返回数据。之后客户是如何接收这个数据并对其进行操作的呢?
其实在代码17.2中的第3行就已经给出了答案了,即通过回调函数。AJAX在发送请求的时候,同时也对XmlHttpRequest对象的onreadystatechange属性赋了一个函数,这个就是AJAX的回调函数。当AJAX发送请求时,这个函数就能监听这个请求的过程,具体状态反映在XmlHttpRequest对象的readyState上。该属性值的各个数值和意义如下所示。
- 0表示对象已建立,但是尚未初始化(尚未调用open方法)。
- 1表示对象已建立,尚未调用send方法。
- 2表示send方法已调用,但是当前的状态及HTTP头未知。
- 3表示已接收部分数据,因为响应及HTTP头不全,这时通过responseBody和responseText获取部分数据会出现错误。
- 4表示数据接收完毕,此时可以通过responseBody和responseText获取完整的回应数据。
所以当该属性值为4时,表示响应加载完毕。这时XmlHttpRequest对象的另一个属性responseText存放了服务器文本格式的响应,也就是说,服务器将请求的处理结果填充到XmlHttpRequest对象的responseText属性中。知道了这两点,完成回调函数就顺理成章、水到渠成了。代码17-3就是处理服务器响应的JavaScript函数的一个实现。
代码17-3 处理服务器响应的JavaScript程序
function callBack() { if(xmlHttp.readyState == 4) { var response = xmlHttp.responseText; alert(response); } }
这段处理服务器响应的代码看起来要比发出请求的JavaScript代码简单。该函数等待服务器的调用,当服务器处理完请求,就会调用该函数。代码第3行判断XmlHttpRequest对象的readyState属性的值是否为4,如果为4,则通过XmlHttpRequest对象的responseText获取服务器的响应数据,如代码第5行所示。最后通过alert()函数将得到的结果显示出来,如代码第6行所示。AJAX正是在这里实现了页面没有刷新,但页面内容却被更新的效果。
17.3.4 一个基于AJAX的用户名验证程序
通过以上三个小节的学习,相信读者已经对AJAX的实现机制有了一个整体性的了解。本节主要是结合学过的知识来做一个基于AJAX的用户名验证程序,以此能让读者对AJAX有一个更深刻的了解。
这个程序主要由三部分组成,一是客户端的表单,含有用户名和密码的输入框,二是服务器端的响应程序,第三就是连接客户端和服务器端的桥梁AJAX。然后这个程序会对提交上来的用户名做判断,如果成功则返回欢迎消息,如果出错则出现提示。代码17-4就是实现了这个功能的客户端代码。
代码17-4 验证表单HTML页面
<span class="kindle-cn-bold">一个基于AJAX的用户名验证程序</span><hr /> <script type="text/javascript"> function getXmlHttpRequest() { var xmlHttp=null; //创建一个变量 try { xmlHttp = new XMLHttpRequest(); //对于Firefox等浏览器 } catch(e) { try { xmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); //对于IE浏览器 } catch (e) { try { xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch(e) { xmlHttp = false; } } } return xmlHttp; } function sendRequest(url, call_back, data) { var data = data || ""; xmlHttp.onreadystatechange = call_back if(data != "") { xmlHttp.open("POST", url, true); //使用POST方法打开一个到url的连接, 为发出请求做准备 //以下为POST方式提交数据,所需要的header xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xmlHttp.setRequestHeader("Content-length", data.length); xmlHttp.setRequestHeader("Connection", "close"); } else { xmlHttp.open("GET", url, true); //使用GET方法打开一个到url的连接, 为发出请求做准备 } xmlHttp.send(data); //发送请求 } function callBack() //回调函数 { if(xmlHttp.readyState == 4) //如果成功 { var response = xmlHttp.responseText; //读取返回值 alert(response); //弹出信息 } } var xmlHttp = getXmlHttpRequest(); //调用getXmlHttpRequest,得到一个XMLHttpRequest对象 function AJAXRequest() { var username = document.getElementById('username').value; var password = document.getElementById('password').value; // POST方式提交数据 sendRequest('17-5.php', callBack, 'username='+username+'&password='+password); } </script> AJAX验证表单: <form id="form1" name="form1" method="post" action=""> <p> 用户名:<input type="text" name="username" id="username" /> </p> <p> 密码:<input type="password" name="password" id="password" /> </p> <p> <input type="button" onclick="AJAXRequest()" value="开始验证" /> </p> </form>
这段代码的JavaScript部分,所用的就是前三节所讲的AJAX实现步骤的JavaScript函数,这里就不再赘述其功能。需要讲解的是AJAXRequest()函数,这个函数首先得到页面中的username和password的值,然后通过sendRequest()向服务器发送一个请求并确定回调函数为callBack()。
代码17-5是完整的服务器端PHP程序。
代码17-5 服务器端验证
<?php header("Content-Type: text/html; charset=gb2312"); //设置编码格式 if($_POST['username'] == 'php' && $_POST['password'] == '123') { echo "你好,欢迎来到PHP的AJAX世界!"; } else { echo "用户名或者密码错误!"; } ?>
以上代码完成服务器的数据处理和请求,这里只是演示一下。当用户名是“php”并且密码为“123”时则显示欢迎消息,否则提示出错。
注意 因为AJAX默认是通过UTF-8编码来传输数据的,所以如果客户端的编码是GB1213格式,那么服务器端输出的内容也需要是GB2312编码格式才能在客户端正常显示。
运行代码17-5以后随便输入一个用户名和密码,单击“开始验证”按钮以后出现如图17.2所示的错误信息。如果是正确的用户名和密码就会出现如图17.3所示的欢迎消息。整个过程中,页面都是没有刷新的。
图17.2 AJAX验证失败的提示 | 图17.3 AJAX验证成功的提示 |
17.4 Spry框架
前面讲解了AJAX的原理和运行机制,但是传输的数据并不是XML格式。原因在于JavaScript对于不同的浏览器操作XML数据的方法会有所不同,使用起来比较麻烦。本节主要讲解如何使用Spry框架来处理XML数据的问题。
17.4.1 Spry框架简介
Spry是一个JavaScript框架,提供强大的AJAX功能,能够让设计人员为用户构建出具有更丰富体验的Web页面。Spry利用HTML、CSS和最少的JavaScript功能将XML、JSON和HTML数据表现在页面中,并且不必刷新整个页面。Spry还提供易于构建和设计的控件,为最终用户提供功能强大的页面元素。Spry框架以HTML为核心,对于只具有HTML、CSS和JavaScript基础知识的用户来说很容易掌握。Spry框架设计成标签时应尽量简单,JavaScript应尽量少用。Spry主要由三部分组成:Spry Data、Spry Widgets和Spry Effects。
Spry是一个Adobe为AJAX量身打造的JavaScript框架。Spry一个非常大的特色就是能够与Adobe的其他产品进行无缝整合使用(如与Dreamweaver、Flash和AIR等)。就像Adobe的其他优秀产品一样,Spry也能提供相当优秀的文档资源,并有一个强大开发团队的支持。
有关Spry框架的详细信息,请访问其官方网站http://labs.adobe.com/technologies/spry/,可以下载最新版本的框架,并且还有使用Spry构建Web页的教程等信息。
17.4.2 Spry框架的使用方法
要使用Spry框架,首先要有这个框架的版本,Spry可以从Adobe官方网站上免费下载,如图17.4所示。
图17.4 Spry框架官方网站
在中间部分可以看到一个有绿色框的表格,单击其中的第一项就可以进入相应的下载页面。如果还不是Adobe的成员,它会提醒先注册。如果已经拥有账户,那么就可以直接登录。登录后就会转到相应的下载页面,选中最新版本的Spry框架下载即可。得到解压缩后的目录如图17.5所示。
图17.5 Spry框架的目录结构
在目录图中可以看到,下载的Spry框架中已经包含大量演示、示例、技术文章和文档。其中的includes目录就包含Spry的核心文件和库文件,widgets目录中包含相关的网页小插件等。
下面通过一个实例讲解如何使用Spry。首先以XML文件的形式创建一些样本数据,其中包含几个人员方面的信息,如代码17-6所示。
代码17-6 Spry显示XML数据
<?php header('Content-Type: text/xml'); //设置XML输出文件头 ?> <employees> <employee id="1"> <name>张大山</name> <email>sansan@163.com</email> <mobilePhone>11612345678</mobilePhone> <department>市场部</department> </employee> <employee id="2"> <name>李桃桃</name> <email>taotao@mahuu.com</email> <mobilePhone>13812345678</mobilePhone> <department>研发部</department> </employee> <employee id="3"> <name>王老虎</name> <email>laohu@yahoo.com.cn</email> <mobilePhone>12345678910</mobilePhone> <department>研发部</department> </employee> </employees>
注意 从以上代码可以发现,这段PHP程序只是单纯的输出XML格式数据。这里只是为了演示需要,在实际开发中读者可以修改这个程序,根据不同的请求来返回不同的数据。
从以上代码中可以看到很多行数据,每行包含相同的属性,Spry与XML交互不需要DTD(数据类型定义),这是处理XML的一个典型问题,但并不是标准。此处,这个示例的目的是使用Spry处理数据,然后输出到一个HTML页中,所以可以命名数据的属性并告知Spry在页面的那个位置显示它们。代码17-7就是实现这一过程的完整代码。
代码17-7 使用Spry显示XML数据
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:spry="http://ns.adobe.com/spry"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script type="text/javascript" src="../spry/includes/xpath.js"></script> <script type="text/javascript" src="../spry/includes/SpryData.js"></script> <title>使用Spry来显示XML数据</title> <script type="text/javascript"> var ds1 = new Spry.Data.XMLDataSet("17-6.php", "employees/employee"); </script> </head> <body> <span class="kindle-cn-bold">使用Spry来显示XML数据</span><hr /><br /> 显示数据如下:<br /><br /> <div spry:region="ds1"> <table cellpadding="3" border="1"> <tr> <th>姓名</th> <th>电子邮件</th> <th>移动电话</th> <th>所属部门</th> </tr> <tr spry:repeat="ds1"> <td>{name}</td> <td>{email}</td> <td>{mobilePhone}</td> <td>{department}</td> </tr> </table> </div> </body> </html>
首先,需要引入两个JavaScript文件:第一个文件为了利用XPath使用了Google的开源代码;第二个文件是Spry数据库,它依赖XPath库,这也是为什么使用时要先声明的原因。
其次,声明了一个Spry XMLDataSet实例,此处将它命名为ds1。初始化要求两个参数:XML文件的位置和一个用来识别XML节点或包含数据的节点的XPath表达式。XML还可以从一个URL加载。注意,XPath表达式识别XML的根节点,然后识别代表每行数据的子节点。
最后,在页面的主体部分输出Spry数据集。Spry动态区用于在页面上显示XML数据,当数据集改变时它们会同时更新。一个动态区使用spry:region在一个div标记中声明,HTML标记作为动态区容器。动态区是Spry数据集的一个“观测区”,用括号区别数据集中的每个列,spry:repeat标记迭代显示数据集中的所有行。
运行以上程序后,得到的效果如图17.6所示。
图17.6 使用Spry显示XML数据的结果
17.4.3 Spry框架与Macromedia Dreamweaver的结合
Spry最大的特点就是它与Macromedia Dreamweaver的结合,使用Dreamweaver可以图形化地编写Spry代码。当然这样做有个前提,需要Dreamweaver的版本在CS3以上。本节就是用Srpy框架与Macromedia Dreamweaver的结合来开发17.4.2节中的例子。
(1)首先需要打开Dreamweaver,新建一个html文件,如图17.7所示。
图17.7 使用Dreamweaver新建一个html文件
(2)在左边的空白页面中单击一下,使鼠标的焦点落在此处。然后单击右边的Spry快捷窗口中的“Spry数据集”。如果没有保存文档,会提示需要保存文档,这里为了需要将它保存为“17-8.html”。之后便会弹出一个创建Spry对象的窗口。因为使用的是XML数据,所以在选择数据类型时,选择XML。指定数据文件为“17-6.php”。之后窗口中会显示被选择的XML文件的结构,这里使用鼠标选中第二层节点,如图17.8所示。
图17.8 选取数据源
(3)之后单击“下一个”按钮,出现的配置数据字段界面如图17.9所示。
图17.9 配置数据字段
(4)在这个界面可以设置字段类型和列排序的方式等内容,但是在本例中并不需要设置这些,直接单击“下一个”按钮。然后出现如图17.10所示的界面。
图17.10 选择显示的HTML格式
(5)因为格式需要显示在表格中,所以在这里选择的是第一项“插入表格”。在这个页面中的每一个选项还有相应的设置,单击“设置”按钮进入后即可进行设置。最后单击“完成”按钮,保存文件。其间会提示是否需要插入“xpath.js”和“SpryData.js”两个文件,单击“是”按钮,则系统将自动创建SpryAssets目录并把相应的文件加入到页面中。如果不希望系统这样做,也可以单击“否”按钮,此后就需要采用手动方式来引入这两个JavaScript文件了。
(6)最后对其做一些界面上的修改,得到的效果如图17.11所示。
图17.11 最终效果
生成的代码如代码17-8所示。
代码17-8 Srpy框架与Macromedia Dreamweaver的结合
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:spry="http://ns.adobe.com/spry"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Srpy框架与Macromedia Dreamweaver的结合</title> <script src="SpryAssets/xpath.js" type="text/javascript"></script> <script src="SpryAssets/SpryData.js" type="text/javascript"></script> <script type="text/javascript"> var ds1 = new Spry.Data.XMLDataSet("17-6.php", "employees/employee"); </script> </head> <body> <span class="kindle-cn-bold">Srpy框架与Macromedia Dreamweaver的结合</span><hr /> 显示数据如下:<br /><br /> <div spry:region="ds1"> <table border="1" cellpadding="3"> <tr> <th spry:sort="name">名字</th> <th spry:sort="email">电子邮件</th> <th spry:sort="mobilePhone">移动电话</th> <th spry:sort="department">所属部门</th> <th spry:sort="@id">编号</th> </tr> <tr spry:repeat="ds1"> <td>{name}</td> <td>{email}</td> <td>{mobilePhone}</td> <td>{department}</td> <td>{@id}</td> </tr> </table> </div> </body> </html>
由以上代码可以看到,基本与17.4.3节中的例子是差不多的,但是这段代码是使用图形化界面一步一步生成的。运行以后的效果如图17.12所示,单击“电子邮件”表头表格还会自动排序,如图17.13所示。
图17.12 使用Dreamweaver做出的效果 | 图17.13 表格自动排序 |
17.4.4 使用Spry制作级联下拉菜单
经过前面几节的介绍和学习,想必读者已经对Spry有了一定的了解,这节就使用Spry框架一起来做个很流行的AJAX效果——无刷新的级联下拉菜单。
首先需要定义两个数据用来做相关的显示。代码17-9是一个含有几个父亲名字的文件,它返回的格式为XML。代码17-10是与代码17-9文件中父亲对应的儿子的列表文件,它会根据提交的参数不同,返回不同数据集合。
代码17-9 父亲名字
<?php header('Content-Type: text/xml'); //设置XML输出文件头 ?> <root> <father id="1"> <name>张三</name> </father> <father id="2"> <name>李四</name> </father> <father id="3"> <name>王五</name> </father> </root>
代码17-10 返回相应的儿子名字
<?php header('Content-Type: text/xml'); //设置XML输出文件头 ?> <root> <?php if($_REQUEST['father_id'] == 1):?> <child> <name>张小三</name> </child> <child> <name>张三三</name> </child> <?php elseif($_REQUEST['father_id'] == 2):?> <child> <name>李小四</name> </child> <child> <name>李四一</name> </child> <child> <name>李四二</name> </child> <child> <name>李四三</name> </child> <child> <name>李四四</name> </child> <?php elseif($_REQUEST['father_id'] == 3):?> <child> <name>王小五</name> </child> <child> <name>王五五</name> </child> <?php endif;?> </root>
有了以上数据基础后,就可以实现客户端的代码了。代码17-11是实现了需要功能的实例,如下所示。
代码17-11 使用Spry制作级联下拉菜单
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:spry="http://ns.adobe.com/spry"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>使用Spry制作级联下拉菜单</title> <script src="../spry/includes/xpath.js" type="text/javascript"></script> <script src="../spry/includes/SpryData.js" type="text/javascript"></script> <script type="text/javascript"> var ds_father = new Spry.Data.XMLDataSet("17-9.php", "root/father"); //创建XMLDataSet对象 var ds_child = new Spry.Data.XMLDataSet("17-10.php", "root/child"); //创建XMLDataSet对象 function re_load() { var father_id = document.getElementById('father').value; //读取选择的ID ds_child.setURL("17-10.php?father_id=" + father_id); //重新载入XMLDataSet对象 ds_child.loadData(); //更新数据 return false; } </script> <style type="text/css"> body,td,th,select { font-family: Arial, Helvetica, sans-serif; font-size: 14px; } </style> </head> <body> <span class="kindle-cn-bold">联级下拉菜单</span><hr /> <span spry:region="ds_father"> <span spry:state="loading">数据加载中...</span> <span spry:state="failed">数据加载错误!</span> <span spry:state="ready">父亲: <select name="father" id="father" onchange="re_load()"> <option value="" selected="selected">请选择</option> <option value="{@id}" spry:repeat="ds_father">{name}</option> </select> </span> </span> <span spry:region="ds_child"> <span spry:state="loading">数据加载中...</span> <span spry:state="failed">数据加载错误!</span> <span spry:state="ready">儿子: <select name="child" id="child"> <option value="" selected="selected">请选择</option> <option value="{name}" spry:repeat="ds_child">{name}</option> </select> </span> </span> </body> </html>
同样,程序开始都需要先载入Spry的两个核心文件“xpath.js”和“SpryData.js”,这一步可以手动添加也可使用Dreamweaver自动载入。其后使用Spry.Data.XMLDataSet分别创建“父亲”数据集和“儿子”数据集,并绑定在HTML代码中。
程序的关键在于对“父亲”下拉列表添加了一个onchange实践并绑定函数为re_load()。所以当这个下拉列表有变化的时候就会执行re_load()函数。下面详细分析此函数所做的处理。
首先使用document.getElementById()方法得到选中的值,然后使用ds_child对象的setURL属性重新载入对应的数据,最后调用该对象的loadData()函数更新客户端数据。
程序运行后,选择“李四”后的结果如图17.14所示,选择“王五”后的结果如图17.15所示。
图17.14 选择“李四”后的结果 | 图17.15 选择“王五”后的结果 |
17.5 典型实例
【实例17-1】所谓的选择器,就是上例中介绍的构造函数的第一种形式,在此称为选择器。
选择器可以帮助开发人员,从众多的页面元素中查找并选择需要的元素,然后将这个元素转换为jQuery的对象并返回。
本例将演示如何利用选择器,选择其他页面元素。
选择器可以接收的参数类型包括以下5种:
- ID:页面元素的ID值定位页面元素,可以精确地选择某一个页面元素。
- 名称:页面元素的名称,例如“div”、“a”等,可以用于选择同类型的所有元素。
- 关键字class:根据class关键字定位页面元素,可以用于选择使用同一样式的元素。
- 多选:多选不同于全选,多选可以使用上面介绍的3种形式,选择不同类型的元素。
- “*”:选择页面所有元素即全选。
选择器根据参数查检页面,如果需要选择的元素存在,将返回jQuery对象。
以上介绍的5种选择器参数类型,是最基本也是最常见的形式。除此之外选择器的参数还包括很多属性,例如线、过滤器、表单、表单过滤器等,在此就不一一介绍了,感兴趣的读者可以查询jQuery的技术文档。
代码17-12 利用选择器选择其他页面元素
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="en_US" xml:lang="en_US"> <head> <title>jQuery演示</title> <!--引用jQuery代码--> <script language="javascript" type="text/javascript" src="js/jquery-1.2.6.js"></script> <!--创建javascript代码--> <script language="javascript" type="text/javascript"> <!--构造函数可以接收的第四类参数:回调函数--> $(function(){ <!--使用ID选择页面元素--> $("#Layer1").css("border","3px solid red"); $("#Layer1").find("li").css("border","3px solid black"); $("#Layer2").css("border","3px solid black"); $("#Layer2 > li").css("border","3px solid red"); <!--使用元素名称选择页面元素--> $("p").css("border","3px solid blue"); <!--使用CSS表达式选择页面元素--> $(".Layer3").css("border","3px solid gray"); <!--同时选择不同类型的元素--> $("span,.div4,#div5,div > p").css("border","3px solid yellow"); }); </script> <style type="text/css"> <!-- #Layer1 { position:absolute; left:17px; top:220px; width:100px; height:100px; z-index:1; } #Layer2 { position:absolute; left:133px; top:220px; width:100px; height:100px; z-index:2; } .Layer3 { position:absolute; left:248px; top:220px; width:100px; height:100px; z-index:3; } --> </style> </head> <body> <div id="Layer1">第一层<li>第一行</li><li>第二行</li></div> <div id="Layer2">第二层<li>第一行</li><li>第二行</li></div> <div class="Layer3">第三层</div> <p id=p1>行1</p><p id=p2>行2</p> <span>第三层</span> <div class="div4">第四层</div> <div id="div5">第五层</div> <div><p>第六层</p></div> </body> </html>
运行该程序,运行结果如图17.16所示。
图17.16 程序运行结果
【实例17-2】前面的实例只是客户端代码,本实例演示客户端、服务端代码的编写方法。
使用jQuery可以构建AJAX的客户端,而AJAX的服务器端可以响应的形式有JavaScript脚本、XML、JSON等格式。通过PHP有效地管理服务器端的数据,可以完成一个根据不同请求,返回不同数据内容的服务器端。
AJAX客户端代码如下所示。
代码17-13 客户端、服务端代码的编写方法
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="en_US" xml:lang="en_US"> <head> <title>jQuery演示</title> <!--引用jQuery代码--> <script language="javascript" type="text/javascript" src="js/jquery-1.2.6.js"></script> <!--创建javascript代码--> <script type="text/javascript"> $(function(){ //添加6个按钮 $.each({0:"使用GET方法请求数据", 1: "使用POST提交表单数据", 2: "同步更新数据", 3: "使用$.get获取服务器数据", 4: "使用$.post获取服务器数据", 5: "处理Error"},function(i, n){ $("<input type=button>") .appendTo($('body')) //将按钮添加至表单中 .val(n); //设置按钮的值 }); //添加一个用于显示信息的div $("<div class='message'>消息显示</div>").appendTo($('body')); //找出所有按钮 $('input:button').eq(0) .click(function(){ //为表单中的第一个按钮绑定单击事件 //使用$.ajax的get方法,加载JavaScript脚本 $.ajax({ //使用AJAX方法 type:"GET", //设置提交数据方式为GET url:"demo.js", //url指向需要加载的脚本文件 dataType:"script" //注意加载JavaScript脚本时,dataType属性的值 }); }) .end().eq(1) .click(function(){ //使用$.ajax的post方法,向服务器端提交数据 $.ajax({ type: "POST", //数据传递方法为POST url: "ajaxServices.php", //url属性的值指向服务器端文件 //data属性的值是向服务器端提交的数据 data: "action=save&title=客户端数据&detail=保存到服务器端", //success属性的值是一个回调函数,用于在数据提交成功后,处理返回数据 success: function(msg){ //获取数据成功后,将数据显示在相关元素中 $(".message").append("<li>"+msg+"</li>"); } }); }) .end().eq(2) .click(function(){ //使用$.ajax实现客户端同步服务器端数据 //关键属性async的值必须为false var html = $.ajax({ url: "ajaxServices.php?action=getHtml", async: false }).responseText; $(".message").append("<li>"+html+"</li>"); }) .end().eq(3) .click(function(){ //使用$.get()方法,获取服务器端的数据 $.get( "ajaxServices.php", //设置服务器脚本 { action:"methodGet"}, //设置数据获取方式 function(msg){ //设置回调函数 $(".message").append("<li>"+msg+"</li>"); } ); }) .end().eq(4) .click(function(){ //使用$.post()方法,获取服务器端的数据 $.post( "ajaxServices.php", //设置服务器脚本 { action:"methodPost"}, function(msg){ $(".message").append("<li>"+msg+"</li>"); } ); }) .end().eq(5) .click(function(){ //向一个不存在的文件发送数据请求,以产生错误信息 var html = $.ajax({ url: "none.php", async: false }).responseText; //使用ajaxError()来处理错误信息 $(".message").ajaxError( function(request, settings){ $(this).append("<li>AJAX错误</li>"); //将错误信息显示在相关元素中 } ); } ) }); </script> <style type="text/css"> .message{ padding: 20px; background-color: #000000; color: #FFFFFF; font-weight: bold; width: 200px; } </style> </head> <body> </body> </html>
运行该程序后,运行结果如图17.17所示。
图17.17 程序运行结果
在上面的代码中,当用户单击按钮时,会向服务端的ajaxServices.php中发送ajax请求,ajaxServices.php代码如下所示。
代码17-14 当用户单击按钮后的情况
<?php //判断是否有数据提交 if(isset($_REQUEST["action"])){ $action = strval($_REQUEST["action"]); //根据$action变量,来输出相应的内容 switch($action){ case "save": //当用户提交的数据会save时,运行以下代码 $title = $_POST['title']; $detail = $_POST['detail']; file_put_contents("fromClient.txt",$title."<br>".$detail); print "OK"; break; case "getHtml": //当用户提交的数据是getHtml时,输出日期信息 print(date("Y-m-d H:i:s")); break; case "methodGet": //当用户提交的数据是methodGet时,显示get print("get"); break; case "methodPost": //当用户提交的数据是methodPOST时,显示post print("post"); break; } }else{ //输出约定的错误信息 print("error"); } ?>
在编写完服务器端代码,运行Ch17-4.html文件,并单击各个按钮,就可以得到服务器端的影响,运行结果如图17.18所示。
图17.18 运行结果
17.6 小结
本节介绍了AJAX及其和PHP有关的内容,主要讲述的知识点包括以下内容。
- 什么是AJAX。
- AJAX的工作原理。
- 如何使用AJAX,包括创建XMLHttpRequest对象、发送异步请求、回调函数的编写,最后通过完整实例介绍PHP程序结合AJAX的应用。
- 使用Spry框架来简化AJAX的开发。
17.7 习题
一、填空题
1. AJAX全称为“_____”(异步JavaScript和XML),是指一种创建交互式网页应用的_____技术,使浏览器可以为用户提供更为自然的浏览体验。。
2. AJAX是运行在浏览器端的技术,它在_____端和_____端之间使用异步技术传输数据。但完整的AJAX的应用还需要服务器端的支持,因为浏览器端发出的请求将要由服务器端处理并返回结果。
二、选择题
1. 以下哪一个Web应用不属于AJAX应用( )。
A. Hotmail
B. GMaps
C. Flickr
D. Windows Live
2. 以下哪个技术不是AJAX技术体系的组成部分( )。
A. XMLHttpRequest
B. DHTML
C. CSS
D. DOM
3. XMLHttpRequest对象有几个返回状态值( )。
A. 3
B. 4
C. 5
D. 6
三、简答题
1. AJAX的全称是什么?介绍一下AJAX。
2. 简述AJAX的工作原理。
3. 介绍一下XMLHttpRequest对象的常用方法和属性。
共有条评论 网友评论