本想翻译IBM的一篇文章 Build apps using Asynchronous JavaScript with XML 但是发现不如就按照那个方式想怎么写就怎么写。之后有时间了会把其中的一个系列从基本应用到使用DWR框架的翻出来,也许对一些被AJAX buzz word一直骚扰但是没亲密接触的人有些用处。嗯,把dojo也列入计划吧,但愿我能坚持。
由于JAVA版 servlet+web.xml配置起来稍显麻烦,而且此处主要介绍前端javascript,并且是入门文章,所以来个PHP版本,算是IBM意译PHP Ver.我会把code workthrough伴随在讲解当中。
AJAX是asynchronous javascript and xml的简称。异步是通过由XMLHttpRequest对象替代传统页面刷新式请求来实现,异步的目的是提供更加连续的 友好的用户交互。我想大多数人都讨厌等待浏览器的processBar蓝色慢慢变长的无聊过程和枯燥的白色无响应页面。
那组成AJAX的几项关键技术 javascript css DOM XMLHttpRequest,可能只有XMLHttpRequest对我们来说是相对来说陌生的,前3项,只要做过web app的都不可以说不了解。
XMLHttpRequest:XMLHttpRequest是一个可以让用户不刷新页面的前提下直接提交和得到xml数据的对象。
这并不是一个xx组织的标准产生物,所以要得到一个这样的对象,是通过不同浏览器的扩展来实现。IE通过ActiveX Object来提供,所以大多数ajax应用会看到对象的产生过程都有对浏览器的判断以达到兼容。不要开始大骂MS,平台给我们带来的麻烦并非都是微软造成。对于此对象,我不是个历史学家,所以只能稍微查找些资料来了解。
It is not yet being embodied in any public standard (although something similar is in the works for the proposed W3C DOM Level 3 Load and Save spec)from XML.COM所以它不是一个标准而微软不去执行的例子。
Microsoft first implemented the XMLHttpRequest object in Internet Explorer 5 for Windows as an ActiveX object. Engineers on the Mozilla project implemented a compatible native version for Mozilla 1.0 (and Netscape 7). Apple has done the same starting with Safari 1.2. from apple.com
所以,可以感谢一下微软,还是做了些创新的,估计是为了他的EXChangeServer的web client端服务的……我猜我猜。
Similar functionality is covered in a proposed W3C standard, Document Object Model (DOM) Level 3 Load and Save Specification. In the meantime, growing support for the XMLHttpRequest
object means that is has become a de facto standard that will likely be supported even after the W3C specification becomes final and starts being implemented in released browsers (whenever that might be).from apple.com
所以我们还是要通过如下代码方式创建一个对象:
function init() {
if (window.XMLHttpRequest) {
req = new XMLHttpRequest();
} else if (window.ActiveXObject) {
window.alert("ActiveXObject");
req = new ActiveXObject("Microsoft.XMLHTTP");
}
var url = "server.php";
req.open("POST", url, true);
req.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
}
通过对不同浏览器的判断,产生不同的对象。我想大至大家了解了此对象用处,http请求也是在一些标准协议中定义的header之后以名称,值对的方式来向服务器发送,作为xml天生对数据良好描述的本领,担任此任务小case,但是对于文件上穿等,还是用传统form来解决滴吧。
备考:Table 1. Common XMLHttpRequest Object Methods
|
Method |
Description |
abort() |
Stops the current request |
getAllResponseHeaders() |
Returns complete set of headers (labels and values) as a string |
getResponseHeader("headerLabel") |
Returns the string value of a single header label |
open("method", "URL"[, asyncFlag[, "userName"[, "password"]]]) |
Assigns destination URL, method, and other optional attributes of a pending request |
send(content) |
Transmits the request, optionally with postable string or DOM object data |
setRequestHeader("label", "value") |
Assigns a label/value pair to the header to be sent with a request |
好了,废话讲完了,开始菜鸟级别的亲密接触。我想ajax是有应用场景的,那么我举个我感觉很贴切的应用场景,在论坛注册的时候,验证是否已经存在你要注册的用户名。在没有ajax之前,我们都要单独点一个button,弹出新窗口等待结果。这里面我们使用户输入完了用户名之后,不影响其正常填写其他内容,神不知鬼不觉地完成验证并提醒客户是否已经有人注册了。
首先构建一个注册画面 regForm.php
<html>
<head>
<script type="text/javascript" src="ajax.js" >
</script>
</head>
<body>
<font face="Arial,Helvetica,Verdana" size="3">
<form name="regForm" action="reg.php">
<b>Enter Your User ID: </b>
<input type="text" name="userID" onblur="validate(this.form)"/>
<!--Message -->
<span id="msg"></span>
<br/>
<input type=”password” name=”pwd”/>
.other input filed
<hr>
</body>
</html>
好啦,一个丑陋无比的注册页面搞定了。
紧接着,完成我们的ajax.js文件
var req;
var url;
定义req url全局变量 一个用来表示XMLHttpReqeust一个表示请求的服务器端资源。
function init() {
//。。。。。看上面
}
function validate(formObj) {
init();
req.onreadystatechange = userIDValidator;
req.send("userID ="+formObj.userID.value);
}
此函数便是当用户输入完了用户名,自鸣得意的去输入其他的文本域时触发的事件,它悄悄地执行。由于在init()函数中我们如此设置req.open("POST", url, true);最后一个参数true就是异步的设置所在,如果未false,效果大家看看msn spaces的流言就知道了,叶面虽然不刷新但是要停止响应一段时间,嗯,给你点看字的机会却不让你滚动边上可爱的scroll翻页。
既然我们设置了异步处理,那么执行完了通知谁啊?通过此句req.onreadystatechange = userIDValidator;当req状态改变的时候,执行userIDValidator。这是一个回调函数的应用,不理解啥是回调没关系,总之req状态改变了,就执行此函数名字的函数(你也可以写匿名函数req.onreadystatechange=new Function{javascript真伟大}).一切就绪,向服务器发送请求。Send()方法中传递请求的参数。
当服务器响应了呢?那就是userIDValidator要干活的时候啦。
function userIDValidator() {
if (req.readystate == 4) {
if (req.status == 200) {
if(req.responseText!=”true”){
window.alert(“你怎么注册别人有的用户名啊?”);
document.getElementById(“msg”).innerHTML=”换一个换一个”;
};
}
}
}
req.readystate == 4代表请求响应完成 具体的代码意义如下
0 = uninitialized
1 = loading
2 = loaded
3 = interactive
4 = complete
req.status == 200这个是标准的http响应状态码,有些时候你的ajax应用响应石沉大海,你就可以输出这个req.status调试一下,看看是不是出现了404 202等咚咚。
待会我们看见那个极其简单的服务器端php文件返回的text/html普通响应,所以此刻我们用req.responseText。其实稍微复杂一些的应用都要返回xml作为响应结果,然后客户端用脚本解析xml文件再通过操作DOM来改变页面内对象的内容或者结构等。也可以返回的xml对象通过xslt来解析,不过增加了学习的曲线。服务器端产生xml对象也是繁琐的工程,所以出现了很多现成的框架帮助简化开发,比如国产buffalo,洋货DWR等,通过与前端dojo Rico等框架组合,产生强大的交互功能,一流的用户体验。
那么简单的xml操作可参考ibm文章中做法:
var messageObj = req.responseXML.getElementsByTagName("message")[0];
var message = messageObj.childNodes[0].nodeValue;
if (message == "true") {
msg.innerHTML = "Subscription is valid";
document.forms[0].order.disabled = false;
} else {
msg.innerHTML = "Subscription not valid";
document.forms[0].order.disabled = true;
}
ok了,看看服务器端庐山真面目吧。
<?php
$userid = $_POST['userid'];
echo "true";
?>
我靠,太简单了吧,你耍我呢啊?这个……我用写全么?无非就是
<?php
echo isValide($_POST['userid']);
?>
isValide()中连接数据库,查询,返回结果……
ok,你已经可以神不知鬼不觉地检查用户名,然后突然弹出窗口提示用户,你的名字不对。
下一教程应该是谈论对象序列化和反序列化问题 之后是DWR 之后是dojo 之后是javascript的debug 之后是buffalo 之后是……之后是……