2.1. The Old-Fashioned Way

2.1. The Old-Fashioned Way

首先,我们来看一个Ajax的简单实例:点击一个链接,使用XMLHttpRequest呈现一个从服务器返回的回应。在这个实例中不使用Prototype或者是Rails JavaScript辅助器。
 
有时候,人们常常觉得使用XMLHttpRequest技术非常复杂,但是下面通过一些小练习和一组新概念,你会觉得这个东西并不像人们说的那样。
2.1.1. Starting a Project(创建一个项目)
在终端下输入:
rails ajaxonrails
cd ajaxonrails
ruby script/server
 
打开浏览器[url]http://localhost:3000[/url]会看到rails的欢迎画面。再打开一个终端,创建一个名字叫Chapter2Controller的控制器和一个myaction的action(一个终端在运行http服务,你这时可以另外打开一个终端)
script/generate controller chapter2 myaction
 
myaction.rhtml中添加下面的代码
 

<p><a href="#" onclick="alert('Hello !');">Inline alert(  )</a></p>
 
这里创建了一个段落<p></p>这里有一个基本的链接,但是没使用通常使用的href属性,而使用了onclick,这个onclick后面提供了一个要运行的Javascript片段。下面刷新浏览器,点击这个链接,会看到下图的效果
2.1. The Old-Fashioned Way
 
在onclick属性里面加上一些代码,马上就会变得复杂起来,下面我们修改这段代码来实现一个新的javascript功能:
 
<p><a href="#" onclick="customAlert(  );">Call custom function</a></p> 
<script type="text/javascript"
  function customAlert(  ) { 
    alert('Hello from a custom function.'); 
  } 
</script>
再刷新浏览器,看看会发生什么?结果本质上跟上面的是一样的。
 
好了,热身完毕。下面做一下Ajax的练习(要记得,我们在这张结束之前都是在窥探Javascript底层的东西,Rails框架会隐藏很多javascript的复杂性)首先,我们需要定义一个新的action,名字myresponse.再新建一个myresponse.rhtml,里面的代码:
Hello from the server.
回到myaction.rhtml,添加一些HTML和Javascript进去:
<p><a href="#" onclick="serverSideAlert(  );">Call server-side function</a></p> 
<script type="text/javascript"
  function serverSideAlert(  ) { 
    var request = new XMLHttpRequest(  ); 
    request.open('get', '/chapter2/myresponse', false); 
    request.send(null); 
    alert(request.responseText); 
  } 
</script> 
再次打开[url]http://localhost:3000/chapter2/myaction[/url],,点击新链接,如果一切顺利,会出现如下图所示的结果:
2.1. The Old-Fashioned Way
这里需要特别说明下,如果是IE浏览器而版本是IE7以下,运行会出现问题(后面会讲解这个问题)
现在,我们取得了一点小成就。为了让自己相信,来看看终端中(运行script/server)的提示信息,每次你点击Ajax的链接时,就会有这些信息出现:
Processing Chapter2Controller#myresponse [GET]
  Parameters: {"action"=>"myresponse", "controller"=>"chapter2"}
Completed in 0.00360 (278 reqs/sec) | Rendering: 0.00027 (7%) | 
  200 OK [[url]http://localhost/chapter2/myresponse[/url]]
现在这个例子中最大的问题就是它在最流行的浏览器IE6下不能工作。这是因为微软执行XMLHttpRequest时将其作为一个ActiveX对象。(实际上两者都依赖于IE的版本),而ActiveX对象必须以一种不同的方式来创建。为了包含这种情况,我们需要创建一个小功能来实现:

<p><a href="#" onclick="IEAlert(  );">Call server(IE-safe)</a></p>
<script type="text/javascript">
  function IEAlert(  ) {
    function getRequestObject(  ) {
      try { return new XMLHttpRequest(  ) } catch (e) {}
      try { return new ActiveXObject("Msxml2.XMLHTTP") } catch (e) {}
      try { return new ActiveXObject("Microsoft.XMLHTTP") } catch (e) {}
      return false
    }
    var request = getRequestObject(  );
    request.open('get', '/chapter2/myresponse', false);
    request.send(null);
    alert(request.responseText);
  }
</script>
这里没有直接创建一个XMLHttpRequest对象,而使用了编写了一个getRequestObject(),在方法体里利用try(一个Javascript的声明用来捕获异常并且阻止异常发生)涵盖了可能出现的情况。(这个例子也给开发者提供了一个思路,在function中定义另一个function)
 
到目前为止,我们其实撒了个小谎,因为前面的Ajax不是异步调用的,request.open()方法中第三个变量决定了不管是不是异步的调用,它的值一直都是false,因此request.send()当请求没有返回之前,让Javascript解释器执行那一行。为了让调用产生异步效果,我们必须重新对一些东西进行整理,在myaction.rhtml中加入下面的代码:
<p><a href="#" onclick="asyncAlert(  )">Call async server-side</a></p> 
<script type="text/javascript"
  function asyncAlert(  ) { 
    function getRequestObject(  ) { 
      try { return new XMLHttpRequest(  ) } catch (e) {} 
      try { return new ActiveXObject("Msxml2.XMLHTTP") } catch (e) {} 
      try { return new ActiveXObject("Microsoft.XMLHTTP") } catch (e) {} 
      return false 
    } 
    var request = getRequestObject(  ); 
    request.open('get', '/chapter2/myresponse'); 
    request.onreadystatechange = function(  ) { 
      if(request.readyState==4) alert(request.responseText); 
    } 
    request.send(  ); 
  } 
</script> 
在前面所有的例子当中,request.send()被改成了request.responseText().现在我们发送的是异步请求了,当请求被引用的同时得到回应是不可能的,为了解决这个问题,XMLHttpRequest对象有一个readyState属性用来改变请求的生命周期。还有另外一个onreadystatechange属性,你可以用onreadystatechange属性来定义一个功能,当readyState每次改变的时候都会调用该功能。在这个例子中,我们定义一个用来检查readyState是4的功能(意思是请求完成;readyState代码在第三章有完整描述),如果检查结果为true,显示一个alert box。




本文转自 fsjoy1983 51CTO博客,原文链接:http://blog.51cto.com/fsjoy/90900,如需转载请自行联系原作者