前端必须掌握ajax,这是几乎所有前端招聘都会要求的一项。

但其实ajax也就是一种异步请求的技术,没有什么很深的东西,不过接触ajax很长一段时间了,早该整理下ajax的学习和使用:

 

PART1: 简单的例子

先通过一个简单地例子开始吧,通过请求一张图片来体验下(需要搭建服务器环境并开启服务器后才能正常使用ajax,以下的所有代码都是在服务器环境下测试的):

 

html:

<!DOCTYPE html>
<html lang="zh-cmn-Hans" id="html">
<head>
  <title>ajax</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta charset="utf-8">
  <meta name="Description" content="SUperman">
</head>
<body>
    <input id="getPic" type="submit" value="提交">
</body>   
<script>
    function ajax(){
      var ajax;
      if(XMLHttpRequest)
        ajax = new XMLHttpRequest();    //IE7+,chrome,firefox
      else
        ajax = new ActiveXObject("Microsoft.XMLHTTP");  //超级老版本的IE
      ajax.onreadystatechange=function(){
        var state = ajax.readyState;
        if(state==4&&ajax.status==200){
          document.body.innerHTML=ajax.responseText;   //responseText就是返回的文本信息
        }
      }
      ajax.open("GET","response.php",true);  
      //三个参数相应表示:发送请求的方式(大小写均可,甚至大小写混用都行,但是可行不代表就应该这么用,还是用大写,培养良好的编程习惯),请求的url,布尔值true表示使用异步的方式
      ajax.send();   //什么数据都不发送
    }
    $("getPic").onclick=function(){
      ajax();
    }
</script>
</html>

 

response.php,返回一个带有src的img标签:

<?php
    echo"<img src='boy.png'></img>"; //返回dom文档片段
?>

 

于是点击按钮,就会通过异步请求的方式获取了一张图片并显示出来。此处省略截图。

 

PART2: 验证ajax异步请求方式

好问的同学此时会有疑惑,虽然open方法的第三个参数设置为true了,可是我怎么知道ajax请求真的就是异步的方式请求而不是同步的呢?

这个问题问得好,在下当时也是这么想的,那咱动手一试便知真伪。

修改下script代码,先看看异步情况是怎样的结果:

    function ajax(){
      var ajax;
      if(XMLHttpRequest)
        ajax = new XMLHttpRequest();
      else
        ajax = new ActiveXObject("Microsoft.XMLHTTP");
      ajax.onreadystatechange=function(){
        var state = ajax.readyState;
        if(state==4&&ajax.status==200){
          document.body.innerHTML=ajax.responseText;
          console.log("ajax完成了,我可以出来了");  //请求发生完成
        }
      }
      ajax.open("GET","response.php",true);
      ajax.send();
      console.log("hi,我是得到响应前的小可爱");    //同步编程
    }

 

看下console的输出情况:

 

从这里可以看出使用的是异步方式,因为并没有等待ajax请求完成才执行下一步操作,console.log("hi,我是得到响应前的小可爱"); 先输出了。

改为同步编程的方式看看:

 

    function ajax(){
      var ajax;
      if(XMLHttpRequest)
        ajax = new XMLHttpRequest();
      else
        ajax = new ActiveXObject("Microsoft.XMLHTTP");
      ajax.onreadystatechange=function(){
        var state = ajax.readyState;
        if(state==4&&ajax.status==200){
          document.body.innerHTML=ajax.responseText;
          console.log("ajax完成了,我可以出来了");  //请求发生完成
        }
      }
      ajax.open("GET","response.php",false);
      ajax.send();
      console.log("hi,我是得到响应前的小可爱");    //同步编程
    }

 

看下console的输出情况:

 

瞧,真的变成同步请求而不是异步请求了诶,先输出了请求完成的语句,这里ajax阻塞了主线程的执行,firefox还温馨提示不推荐使用同步ajax请求方式。

所以为了发挥ajax的真正作用,应该始终记得第三个参数是true,使用异步请求是ajax技术的初衷。

 

PART3: 获取JSON格式数据

由于一般使用JSON格式的数据来进行传输,所以修改下php,使得返回json数据:

<?php
    echo '{"ajax":[{"name":"SUperman","number":1},
    {"name":"苏苏","text":"byebye"}]}';
?>

 

ajax函数也相应的修改:

function ajax(){
      var ajax;
      if(XMLHttpRequest)
        ajax = new XMLHttpRequest();
      else
        ajax = new ActiveXObject("Microsoft.XMLHTTP");
      ajax.onreadystatechange=function(){
        var state = ajax.readyState;
        if(state==4&&ajax.status==200){
          var response = JSON.parse(ajax.responseText);  //转化为JSON对象,ie7-不支持JSON对象
          var array = response['ajax'];
          console.log(response);
          if(array){
            var c = document.createDocumentFragment();
            for(i = 0, len = array.length; i < len; ++i){
              var p = document.createElement("p");
              for(j in array[i])
                p.innerHTML += "<span>"+j+":</span>"+"<span>"+array[i][j]+"   </span>";
              c.appendChild(p);
            }
            document.body.appendChild(c)
          }
        }
      }
      ajax.open("GET","response.php",true);
      ajax.send();
    }

 

通过请求的response看下ajax得到的数据,从php代码也可以知道:

 

要方便的使用json数据要先用JSON.parse()方法(ie7-不支持)将数据转化为JSON对象,浏览器显示的是:

 

PART4: GET方式发送参数及对应的值到后台

现在,除了获取后台的数据,我还想传递参数给后台处理,可以将参数添加在open方法的url后面,如:

ajax.open("POST","response.php?name=某某某&&year=19",true);

 

表示将参数name和year以及对应的值传递给后台,

还是在浏览器开发工具中查看下, parameters就不再是空的了,它显示了要传递的参数:

 

修改下php的代码,使得返回传递的参数和值:

<?php
    echo '{"ajax":[{"name":"'.$_REQUEST['name'].'","number":'.$_REQUEST['year'].'},
    {"name":"苏苏","text":"byebye"}]}';
?>

 

结果如下:

 

看似一切正常。测试下浏览器,firefox和chrome是正常了,但是卧槽这放到ie就是歇菜的节奏啊:

这串"ijijij"哪来的,我的"某某某"呢,不科学!其实呢,这是字符编码的问题了,传递中文字符名-值对时应该先进行uri编码,

像这样:encodeURIComponent("某某某");将字符串作为uri组件单独编码。

修改之后,ie中打开就一切正常了,

从下图可以看出中文字符已经编码了:

 

 

当然啦,写程序就是为了不做重复的工作,可以用encodeURI() 函数将整串的包含请求参数的字符串作为 URI 进行编码。

像这样:ajax.open("GET",encodeURI("response.php?name=某某某&&year=19"),true);妥妥的解决问题。

当涉及传递参数时应先进行编码再发送请求,否则若有中文字符什么的很容易就给跪了。

 

PART5: POST方式如何发送数据呢,据说url不能太长诶

我现在对send()方法感到好奇了,通常各种书本上的例子调用send()都是传递空参数,那怎么利用起来呢,顾名思义,这个方法就是用来传递数据给后台的呀。

尝试修改send()方法:ajax.send("name=苏&&year=7"); 并且设置open方法改为POST的方式,然后悲剧的发现什么都没发生,

parameters显示(当然如果你不肯改为POST方式,那么你会发现请求的parameters是空的,有木有更悲剧-_-||):

 

卧槽,request payload什么鬼,同时发现http请求头部多了一点东西:

 

字符串长16是因为UTF-8 使用一至四个字节为每个字符编码。而中文汉字在utf-8中一般是占3个字节。所以这个长度是对的,但是却不能被后台获取到发送的数据。

赶紧上网找下资料,发现并没有对request payload有深入的讨论,表示有点伤心,但是提到了ajax使用post方式是想模拟表单post的方式来发送数据,也即form data的形式发送数据。

 

———————————————————————   传说中的分割线  ——————————————————————————————

先来看看form表单如何发送请求。

对于这种get方式的form是没问题的:

<form action="response.php" method="GET">
  <input type="text" name="name">
  <input type="text" name="year">
  <input type="submit">
</form>

 

parameters是querystring的形式:

 

而 http请求url是这样的:

 

改为post方式之后,http报头请求的url改变了,不携带参数了(或许这就是parameters是querystring的形式的原因):

 

而且content-type改变了:

 

parameters也相应的变成了Form data的形式,这就是我们要模拟的表单提交数据的方式!

 

另外当将参数添加到表单的action指向的url后面(必须是post方式,否则报错),而不是放在input中,parameters就变成和get方式一样了(再次相信这就是get方式下parameters是querystring的形式的原因)。

还需要指出的是,对于php响应表单的请求返回中文字符时不设置编码格式会跪掉的,给你显示乱码问你怕不怕。

ajax则不会,不过为了程序更加健壮,鲁棒性更强是吧,还是应该在response.php中设置传输的数据编码格式的

header("Content-type: text/html; charset=utf-8");

嗯,完美,再也没有讨厌且恶心的乱码了。

———————————————————————   结尾分割线  ——————————————————————————————

 

 

好了,回到post方式的ajax请求。为了模拟form data格式,要做的就是修改content-type了:

ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

 

现在打开浏览器看看:

一切正常,parameters也是form data形式了。但是奇怪的是firefox中form data显示的name的值没有显示出来,还是将参数作为uri编码再发送吧:encodeURI("name=苏&&year=7"); 这下就能正常下显示了:

 

好像文章后面都要总结,可是也没什么好总结的了,就这样咯,写了好久,表示给跪。

 

-------------------------------转载注明出处^_^:  http://www.cnblogs.com/suspiderweb/

 

posted on 2015-11-27 16:26  SUperman-苏智敏  阅读(1115)  评论(0编辑  收藏  举报