Farseer

导航

Ajax---XmlHttp

终于轮到Ajax最重要也是最核心的XmlHttp了。废话不多说了,翻译一篇文章,这篇文章是Java视线论坛上一个网友推荐的,感觉比Ajax之父(暂且这么称呼,哈哈)推荐的那篇文章好一些,所以还是翻译这篇文章吧。

Web用户界面:Ajax的背后,XmlHttpRequest应用的实例而已
我确信你已经听说过Ajax了,它是采用Html,JavaScript,DOM,Xml创建Web应用的新方式,利用它你可以创建交互性非常好的Web应用。这种交互应用的例子如:Google(Suggest,local,Mail),MSN,Amazon......
如果说Ajax这个术语还算相对较新的话,而它采用的技术可以说是很古老的了。采用这个技术不需要任何新的东西。因为它仅仅是个客户端(浏览器)技术,所以不管采用Java,PHP,甚至PL/SQL来开发Web应用,用这种技术都是可行的。同时,你也不想必须开发过多的客户端代码去处理用户交互,这正是新的框架提供的支持,我们可以称之为基于"Ajax",这非常有趣。现在创建交互良好的Web应用,不需要花费80%的时间放在客户端的开发上,因为这些(代码)可以由服务器端产生。
当然,在采用这种框架之前,了解一下它的原理是非常重要的。所以我用两个例子来写一个简单的介绍文章。
1.加载信息 ,当浏览器处理数据的时候,需要给用户一些提示信息。
2.关联列表,可以很容易地创建关联列表,在很多应用中,要根据一个列表的内容取决于另一个列表。
如果在Safari(译注:苹果的浏览器,没玩过)上测试上面的例子,会发现第一次请求工作的不错,但接下来的请求不能正常工作。为了在Safari上正常工作,必须在发送前,在Http请求头上添加如下内容,只是用来发送一个较早的时间。
httpRequest.setRequestHeader('If-Modified-Since','Sun,3 Jun 1973 00:00:00 GMT'); 

需要了解什么?
第一个比较有趣的东西是XMLHttpRequest,这个对象被大多数浏览器所支持,通常如果项目采用Html和JavaScript,跨浏览器测试是最重要的一个内容(译注:我们好像从来不用关心这个事情,目前还不用开发Linux或者Unix版本的DCM,所以IE是首选)。从Microsoft在IE5上把XmlHttpRequest(译注:微软实现的名称是XmlHttp,而不是XmlHttpRequest)作为Active控件实现以后,它就不再是什么新东西了。而后它也被Moliza,NetScape(7.0),Apple Safari作为内置控件集成。这个对象最初被设计用来加载数据,以XML为背景,它可以加载任何数据。
创建XMLHttpRequest 对象
正如JavaScript,首先是版本问题,因为在MSFT 的世界里XMLHttpRequest 以ActiveX的方式实现,而在其他世界里它是内置组件,必须要不同的方式创建它。创建的方式是探测当前的浏览器是否支持对象,并根据探测的结果创建不同的对象。
if (window.ActiveXObject)
{
    
// Microsoft Way
    httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
}
else if (window.XMLHttpRequest)
{
    
// Others
    httpRequest = new XMLHttpRequest();
}

注意:另一种根据浏览器的版本不同而创建不同的代码的方式是为JavaScript引擎采用条件编译。
另外,如果不能确定客户端的浏览器版本,或者想给移动(mobile)用户用,开发时最好采用较低的版本。Google Mail采用了Basic HTML 的例子。
异步地获取数据
XMLHttpRequestObject 最有趣的地方是它可以在用户交互的背后(译注:在用户没有察觉的情况下,即没有刷新)获取数据。这就是你的应用能给用户大量交互的原因。

httpRequest.open("GET""./getEmployeeList?deptno=10"true); 
httpRequest.onreadystatechange
= function () {processRequest(); } ; 
httpRequest.send(
null); 

open方法可以根据请求的不同设定不同的参数,比如请求的类型,URL,是否同步(译注:这里应该是是否异步,true表示异步,false表示同步)。
"魔力"来自onreadystatechange这个属性,这个属性设定一个事件句柄当readyState属性改变时触发,比如请求发送,加载数据,完成......在这个例子中,当请求正确完成,会触发事件句柄,执行processRequest处理数据。
注意:虽然同步模式是可以实现的,但我认为最好不要用这种模式,因为这样会在请求期间冻结用户的浏览器。
处理响应

正如我上面提到的在事件句柄中魔力发生的地方跟请求的状态有关系,让我们来看一下如何处理请求和响应。

function processRequest()
{
    
if (httpRequest.readyState == 4)
    {
        
if(httpRequest.status == 200)
        {
            
// process data as XML
            httpRequest.responseXML;
            
            
// or Text
            alert(httpRequest.responseText);
        }
        
else
        {
            alert(
"Error loading page\n"+ httpRequest.status +":"+ httpRequest.statusText);
          }
    }
}

readyState属性用来表示响应的数据是否被全部接收到。它的值列表如下;
0.未被初始化(uninitialized )
1.正在加载(loading )
2.加载完毕(loaded )
3.正在交互(interactive )
4.完毕(completed )
在大多数情况下,只要判断状态4就可以了。在我的例子中我等到status==4,然后判断响应的状态。status是服务器返回的状态,比如200是正常返回,404是(译注:URL)没发现。
然后就可以用responseXML把返回当成XML,这样可以用客户端 DOM API操作XML。当然也可以直接用responseText把返回当做字符串处理。
操作数据
现在已经有从请求返回的数据了,XML或者Text,只需要用JavaScript把他们放到页面的某部分就可以了。所有的都是在客户端完成的,在我们进入用例之前先看一个比较简单的例子。
一个简单的XmlHttpRequest例子
发生了什么?
如我上面解释的那样,这段简单代码只是把XmlHttpRequest中的内容拷贝到页面中。

if(httpRequest.status == 200)
{
    
var contentViewer = document.getElementById("contentViewer");
    contentViewer.innerHTML 
= httpRequest.responseText;
}

在大多数情况下,如果仅仅是把得到的内容拷贝到页面中,不需要XML,可是按照下面的步骤进行:
1.用一个特定的ID创建一个DIV标签(或者其他的)
2.用document.getElementById()方法得到想把内容插入其中的元素,这是最简单的方法。
3.只需要用innerHTML 属性呈现DIV的内容。(也可以用 DOM API做同样的事情,但我确信,纯粹主义者会说这是唯一正确的方式)。
在大多数的框架下,数据是用XML来交互的,一般客户端方法都是使数据放到页面的不同组件上。
用例一:显示加载信息
一个普遍的应用是当处理请求的时候在客户端显示一些提示信息。用上面同样的方式,可以显示提示信息直到响应完毕。
在线演示
发生了什么?
这里的技巧只是获取一个区域用来打印信息(比如“正在加载数据......”).当XMLHttpRequest 的状态不为4的时候,用innerHtml属性显示当前的状态。当请求完成的时候将这个区域清空或者如我所做的那样显示返回的内容。

if (httpRequest.readyState == 4)
      {
        
if(httpRequest.status == 200)
        {
          
// print the content of the page
          var contentViewer = document.getElementById("contentViewer");
          contentViewer.innerHTML 
= httpRequest.responseText;
        }
      }
      
else
      {
           
// Print the loading message.
          var contentViewer = document.getElementById("contentViewer");
          contentViewer.innerHTML 
= "<b style='color:red;'>Loading.<b>";
      }

用例二:关联列表
在很多应用中,当一个下拉框的内容被另一个下拉框的内容决定时,我们往往屈从于Form。根据数量的多少,有几种不同的处理方式,比如可以一次性下载所有的数据(主表和明细),并在客户端编程当主表的数据改变时,改变从表的数据。还有一个解决办法是重新加载页面。
利用XMLHttpRequest,只需要在用户改变主表中的值时调用服务器端的方法重新设置从表的值就可以了(当然你可以设置客户端缓存当用相同的参数调用时,不用第二次加载数据,但那是另一回事了)。
在线演示
发生了什么?
没有比前面一个例子更复杂的东西,当主表(例子中是dept )的onChange 事件触发时,调用JavaScript方法正确的参数创建XMLHttpReqeust对象。
然后在Request的处理事件中,把数据作为XML处理,并加到从表(例子中是emp )中。
在这个例子中,我采用了XML,当然如果想用简单的代码,可以把所有的数据写到Html中,然后用innerHtml属性,但这只是实现方式的不同,不是吗?
结论
首先,你已经看到了,Ajax并不是一个新技术,这些技术已经存在许久了,并且已经通过Google,MSN和其他站点让大众感受到了便利。当然术语本身是最近刚刚提出来的。
同时,我展示了几个小例子可以帮助你现在的开发,当然要在客户端改一些代码。Ajax真正的未来在于把它植入到框架中,植入到你正在用的控件中。所以在你的应用中实现这些代码之前看看是否已经存在了满足你需求的解决方案。
你可以在这里下载示例中的源代码,我尽量使代码简洁,把每一个例子的源代码放在单独的Html文件中。




posted on 2005-07-16 23:07  佛西亚  阅读(614)  评论(1)    收藏  举报