前面的话

  在上一篇中,概要地介绍了XHR对象的使用。本文将详细介绍使用XHR对象发送请求的两种方式——GET和POST。下面将以实例的形式来详细说明

GET

  GET是最常见的请求类型,最常用于向服务器查询某些信息,它适用于当URL完全指定请求资源,当请求对服务器没有任何副作用以及当服务器的响应是可缓存的情况下

【数据发送】

  使用GET方式发送请求时,数据被追加到open()方法中URL的末尾

  数据以问号开始,名和值之间用等号链接,名值对之间用和号(&)分隔。使用GET方式发送的数据常常被称为查询字符串

xhr.open("get","example.php?name1=value1&name2=value2",true)

【编码】

  由于URL无法识别特殊字符,所以如果数据中包含特殊字符(如中文),则需要使用encodeURIComponent()进行编码

  [注意]encodeURIComponent()只是6种编解码方法的一种,关于它们的详细信息移步至此

var url = 'test.php' +'?name='  + encodeURIComponent("小火柴");
xhr.open('get',url,true);

  上面的URL被编码为

test.php?name=%E5%B0%8F%E7%%AB%E6%9F%B4

【编码函数】

  下面这个函数可以辅助向现有URL的末尾添加查询字符串参数

function addURLParam(url,name,value){
url += (url.indexOf("?") == -1 ? "?" : "&");
url +=encodeURIComponent(name) + "=" + encodeURIComponent(value);
return url;
}

  这个addURLParam()函数接受三个参数:要添加参数的URL、参数的名称和参数的值。这个函数首先检查URL是否包含问号(以确定是否已经有参数存在)。如果没有,就添加一个问号;否则,就添加一个和号。然后,将参数名称和值进行编码,再添加到URL的末尾。最后返回添加参数之后的URL

var url = 'test.php';
url = addURLParam(url,'name','aaa');
url = addURLParam(url,'data','bbb'); xhr.open('get',url,true);

【缓存】  

  在GET请求中,为了避免缓存的影响,可以向URL添加一个随机数或时间戳

xhr.open('get',url+'&'+Number(new Date()),true);
xhr.open('get',url+'&'+Math.random(),true);

【封装函数】

  下面把使用get方式发送ajax请求的操作封装为get()函数

function get(url,data,callback){
//创建xhr对象
var xhr;
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}else{
xhr = new ActiveXObject('Microsoft.XMLHTTP');
}
//异步接受响应
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
if(xhr.status == 200){
//实际操作
callback && callback(xhr.responseText);
}
}
}
for(var key in data){
url += (url.indexOf("?") == -1 ? "?" : "&");
//编码特殊字符
url += encodeURIComponent(key) + "=" + encodeURIComponent(data[key]);
}
//增加随机数,防止缓存
xhr.open('get',url+'&'+Number(new Date()),true);
//发送请求
xhr.send();
}
//前端
<script>
get('form.php',{
a:1,
b:2,
c:3
},function(data){
//'a:1;b:2;c:3;'
console.log(data);
})
//后端
<?php
foreach($_GET as $key => $value){
if(!empty($value)){
echo $key. ":" .$value .";";
}
}
?>

POST

  使用频率仅次于GET的是POST请求,通常用于服务器发送应该被保存的数据。"POST"方法常用于HTML表单。它在请求主体中包含额外数据且这些数据常存储到服务器上的数据库中。相同URL的重复POST请求从服务器得到的响应可能不同,同时不应该缓存使用这个方法的请求

  POST请求应该把数据作为请求的主体提交,而GET请求传统上不是这样。POST请求的主体可以包含非常多的数据,而且格式不限。在open()方法第一个参数的位置传入"post",就可以初始化一个POST请求

xhr.open("post","example.php",true);

【设置请求头】

  发送POST请求的第二步就是向send()方法中传入某些数据。由于XHR最初的设计主要是为了处理XML,因此可以在此传入XML DOM文档,传入的文档经序列化之后将作为请求主体被提交到服务器。当然,也可以在此传入任何想发送到服务器的字符串

  默认情况下,服务器对POST请求和提交Web表单的请求并不会一视同仁。因此,服务器端必须有程序来读取发送过来的原始数据,并从中解析出有用的部分。不过,可以使用XHR来模仿表单提交:首先将Content-Type头部信息设置为application/x-www-form-urlencoded,也就是表单提交时的内容类型

xhr.setRequestHeader("content-type","application/x-www-form-urlencoded");

  如果不设置Content-Type,发送给服务器的数据就不会出现在$_POSR超级全局变量中。这时要访问同样的数据,须借助$HTTP_RAW_POST_DATA

  如果对相同的头调用多次setReQuestHeader(),新值不会取代之前指定的值。相反,HTTP请求将包含这个头的多个副本或这个头将指定多个值

【发送主体】

  接下来要以适当的格式创建一个字符串,并使用send()方法发送

  POST数据的格式与查询字符串格式相同,名和值之间用等号链接,名值对之间用和号(&)分隔,如下所示

xhr.send('name="abc"&num=123');

【编码和缓存】

  由于使用POST方式传递数据时,需要设置请求头"content-type",这一步骤已经能够自动对特殊字符(如中文)进行编码,所以就不再需要使用encodeURIComponent()方法了

  POST请求主要用于数据提交,相同URL的重复POST请求从服务器得到的响应可能不同,所以不应该缓存使用POST方法的请求

【性能】

  GET对所发送信息的数量有限制,一般在2000个字符。与GET请求相比,POST请求消耗的资源会更多一些。从性能角度来看,以发送相同的数据计,GET请求的速度最多可POST请求的两倍

【封装函数】

  下面把使用post方式发送ajax请求的操作封装为post()函数

function post(url,data,callback){
//创建xhr对象
var xhr;
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}else{
xhr = new ActiveXObject('Microsoft.XMLHTTP');
}
//异步接受响应
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
if(xhr.status == 200){
//实际操作
callback && callback(xhr.responseText);
}
}
}
var strData = '';
for(var key in data){
strData += '&' + key + "=" + data[key];
}
strData = strData.substring(1);
xhr.open('post',url,true);
//设置请求头
xhr.setRequestHeader("content-type","application/x-www-form-urlencoded");
//发送请求
xhr.send(strData);
}
//前端
<script>
post('form.php',{
a:1,
b:2,
c:3
},function(data){
//'a:1;b:2;c:3;'
console.log(data);
})
</script>
//后端
<?php
foreach($_POST as $key => $value){
if(!empty($value)){
echo $key. ":" .$value .";";
}
}
?>

函数封装

  在get和post这两个段落中,分别对get和post这两种方式进行了函数封装。下面对它们进行整合,封装为一个可选择请求方式的ajax()函数,并储存为ajax.js文件

function ajax(obj){
//method为ajax提交的方式,默认为'get'方法
obj.method = obj.method || 'get';
//创建xhr对象
var xhr;
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}else{
xhr = new ActiveXObject('Microsoft.XMLHTTP');
}
//异步接受响应
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
if(xhr.status == 200){
//callback为回调函数,如果不设置则无回调
obj.callback && obj.callback(xhr.responseText);
}
}
}
//创建数据字符串,用来保存要提交的数据
var strData = '';
if(obj.method == 'post'){
for(var key in obj.data){
strData += '&' + key + "=" + obj.data[key];
}
//去掉多余的'&'
strData = strData.substring(1);
xhr.open('post',obj.url,true);
//设置请求头
xhr.setRequestHeader("content-type","application/x-www-form-urlencoded");
//发送请求
xhr.send(strData);
}else{
//如果是get方式,则对字符进行编成
for(var key in obj.data){
strData += '&' + encodeURIComponent(key) + "=" + encodeURIComponent(obj.data[key]);
}
//去掉多余的'&',并增加随机数,防止缓存
strData = strData.substring(1) + '&'+Number(new Date());
xhr.open('get',obj.url+'?'+strData,true);
//发送请求
xhr.send();
}
}
<select name="year" id="year">
<option value="2016">2016</option>
<option value="2017">2017</option>
<option value="2018">2018</option>
</select>
<select name="month" id="month">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<select name="day" id="day">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button id="btn">发送</button>
<span id="result"></span>
<script>
btn.onclick = function(){
ajax({
url:'form.php',
data:{year:year.value,month:month.value,day:day.value},
callback:function(data){
result.innerHTML = data;
}
})
}
</script>
<?php
echo '你选择的日期是' .$_GET['year'] .'年' .$_GET['month'] .'月'.$_GET['day'] .'日';
?>

实例

  下面以一个实例来说明GET和POST两种请求方式的应用

<!-- 前端页面 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
body{font-size: 30px;margin: 0;line-height: 1.5;}
select,button,input{font-size: 30px;line-height: 1.5;}
</style>
</head>
<body>
<h2>员工查询</h2>
<label>请输入员工编号:</label>
<input type="text" id="keyword">
<button id="search">查询</button>
<p id="searchResult"></p> <h2>员工创建</h2>
<form id="postForm">
<label>请输入员工姓名:</label>
<input type="text" name="name"><br>
<label>请输入员工编号:</label>
<input type="text" name="number"><br>
<label>请输入员工性别:</label>
<select name="sex">
<option value="男">男</option>
<option value="女">女</option>
</select><br>
<label>请输入员工职位:</label>
<input type="text" name="job"><br>
<button id="save" type="button">保存</button>
</form>
<p id="createResult"></p>
<script>
/*get*/
//查询
var oSearch = document.getElementById('search');
//get方式添加数据
function addURLParam(url,name,value){
url += (url.indexOf("?") == -1 ? "?" : "&");
url +=encodeURIComponent(name) + "=" + encodeURIComponent(value);
return url;
}
oSearch.onclick = function(){
//创建xhr对象
var xhr;
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}else{
xhr = new ActiveXObject('Microsoft.XMLHTTP');
}
//异步接受响应
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
if(xhr.status == 200){
//实际操作
document.getElementById('searchResult').innerHTML = xhr.responseText;
}else{
alert('发生错误:' + xhr.status);
}
}
}
//发送请求
var url = 'service.php';
url = addURLParam(url,'number',document.getElementById('keyword').value);
xhr.open('get',url,true);
xhr.send();
} /*post*/
//创建
var oSave = document.getElementById('save');
//post方式添加数据
function serialize(form){
var parts = [],field = null,i,len,j,optLen,option,optValue;
for (i=0, len=form.elements.length; i < len; i++){
field = form.elements[i];
switch(field.type){
case "select-one":
case "select-multiple":
if (field.name.length){
for (j=0, optLen = field.options.length; j < optLen; j++){
option = field.options[j];
if (option.selected){
optValue = "";
if (option.hasAttribute){
optValue = (option.hasAttribute("value") ? option.value : option.text);
} else {
optValue = (option.attributes["value"].specified ? option.value : option.text);
}
parts.push(encodeURIComponent(field.name) + "=" + encodeURIComponent(optValue));
}
}
}
break;
case undefined: //fieldset
case "file": //file input
case "submit": //submit button
case "reset": //reset button
case "button": //custom button
break;
case "radio": //radio button
case "checkbox": //checkbox
if (!field.checked){
break;
}
/* falls through */
default:
//don't include form fields without names
if (field.name.length){
parts.push(encodeURIComponent(field.name) + "=" + encodeURIComponent(field.value));
}
}
}
return parts.join("&");
}
oSave.onclick = function(){
//创建xhr对象
var xhr;
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}else{
xhr = new ActiveXObject('Microsoft.XMLHTTP');
}
//异步接受响应
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
if(xhr.status == 200){
//实际操作
document.getElementById('createResult').innerHTML = xhr.responseText;
}else{
alert('发生错误:' + xhr.status);
}
}
}
//发送请求
xhr.open('post','service.php',true);
xhr.setRequestHeader("content-type","application/x-www-form-urlencoded");
xhr.send(serialize(document.getElementById('postForm')));
}
</script>
</body>
</html>
<!-- 后端页面 -->
<?php //用于过滤不安全的字符
function test_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
//设置页面内容的html编码格式是utf-8,内容是纯文本
header("Content-Type:text/plain;charset=utf-8");
//header("Content-Type:application/json;charset=utf-8");
//header("Content-Type:text/xml;charset=utf-8");
//header("Content-Type:text/html;charset=utf-8");
//header("Content-Type:application/javascript;charset=utf-8");
//定义一个多维数组,包含员工的信息,每条员工信息为一个数组
$staff = array(
array("name"=>"洪七","number"=>"101","sex"=>"男","job"=>'总经理'),
array("name"=>"郭靖","number"=>"102","sex"=>"男","job"=>'开发工程师'),
array("name"=>"黄蓉","number"=>"103","sex"=>"女","job"=>'产品经理')
); //判断如果是get请求,则进行搜索;如果是POST请求,则进行新建
//$_SERVER["REQUEST_METHOD"]返回访问页面使用的请求方法
if($_SERVER["REQUEST_METHOD"] == "GET"){
search();
}else if($_SERVER["REQUEST_METHOD"] == "POST"){
create();
} //通过员工编号搜索员工
function search(){
//检查是否有员工编号的参数
//isset检测变量是否设置;empty判断值是否为空
if(!isset($_GET['number']) || empty($_GET['number'])){
echo '参数错误';
return;
}
global $staff;
$number = test_input($_GET['number']);
$result = '没有找到员工'; //遍历$staff多维数组,查找key值为number的员工是否存在。如果存在,则修改返回结果
foreach($staff as $value){
if($value['number'] == $number){
$result = "找到员工:员工编号为" .$value['number'] .",员工姓名为" .$value['name'] .",员工性别为" .$value['sex'] .",员工职位为" .$value['job'];
break;
}
}
echo $result;
} //创建员工
function create(){
//判断信息是否填写完全
if(!isset($_POST['name']) || empty($_POST['name']) ||
!isset($_POST['number']) || empty($_POST['number']) ||
!isset($_POST['sex']) || empty($_POST['sex']) ||
!isset($_POST['job']) || empty($_POST['job'])
){
echo "参数错误,员工信息填写不全";
return;
} echo "员工" .test_input($_POST['name']) ."信息保存成功!";
}
?>

深入理解ajax系列第二篇——请求方式的更多相关文章

  1. 深入理解ajax系列第二篇

    前面的话 在上一篇中,概要地介绍了XHR对象的使用.本文将详细介绍使用XHR对象发送请求的两种方式——GET和POST.下面将以实例的形式来详细说明 GET GET是最常见的请求类型,最常用于向服务器 ...

  2. 深入理解ajax系列第一篇——XHR对象

    × 目录 [1]创建对象 [2]发送请求 [3]接收响应[4]异步处理[5]实例演示 前面的话 ajax是asynchronous javascript and XML的简写,中文翻译是异步的java ...

  3. 深入理解 ajax系列第一篇(XHR 对象)

    1999年,微软公司发布了IE5, 第一次引入新功能:允许javascript 脚本向服务器发起 hffp 请求.这个功能方式并没有被引起注意,知道2004年 Gmail 发布和 Google Map ...

  4. 深入理解ajax系列第九篇——jQuery中的ajax

    前面的话 jQuery提供了一些日常开发中需要的快捷操作,例如load.ajax.get和post等,使用jQuery开发ajax将变得极其简单.这样开发人员就可以将程序开发集中在业务和用户体验上,而 ...

  5. 深入理解ajax系列第九篇

    前面的话 jQuery提供了一些日常开发中需要的快捷操作,例如load.ajax.get和post等,使用jQuery开发ajax将变得极其简单.这样开发人员就可以将程序开发集中在业务和用户体验上,而 ...

  6. 深入理解定时器系列第二篇——被誉为神器的requestAnimationFrame

    × 目录 [1]引入 [2]特点 [3]使用[4]兼容[5]应用 前面的话 与setTimeout和setInterval不同,requestAnimationFrame不需要设置时间间隔.这有什么好 ...

  7. 深入理解javascript函数系列第二篇——函数参数

    × 目录 [1]arguments [2]内部属性 [3]函数重载[4]参数传递 前面的话 javascript函数的参数与大多数其他语言的函数的参数有所不同.函数不介意传递进来多少个参数,也不在乎传 ...

  8. 深入理解javascript作用域系列第二篇——词法作用域和动态作用域

    × 目录 [1]词法 [2]动态 前面的话 大多数时候,我们对作用域产生混乱的主要原因是分不清楚应该按照函数位置的嵌套顺序,还是按照函数的调用顺序进行变量查找.再加上this机制的干扰,使得变量查找极 ...

  9. 深入理解javascript作用域系列第二篇

    前面的话 大多数时候,我们对作用域产生混乱的主要原因是分不清楚应该按照函数位置的嵌套顺序,还是按照函数的调用顺序进行变量查找.再加上this机制的干扰,使得变量查找极易出错.这实际上是由两种作用域工作 ...

随机推荐

  1. Python3与Python2的差异

    基于python3浅谈python3与python2的差异.由于现今主流Python3,但是之前用Python2做的项目,还得维护,所以作为python工作者,不免要了解其中差异,其中,Python2 ...

  2. cloudstack 创建虚拟机失败

    Trying to find a potenial host and associated storage pools from the suitable host/pool lists for th ...

  3. PRML5-神经网络(2)

    本节来自<pattern recognition and machine learning>第5章. 接(PRML5-神经网络(1)) 5.5NN中的正则化 NN的输入层和输出层的单元个数 ...

  4. HDU2552 三足鼎立 【数学推理】

    三足鼎立 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submi ...

  5. 【本地服务器】利用openssl生成证书

    (一)下载openssl软件,解压,进入bin目录 下载地址 (二)1.在当前bin目录,按住shift键右击,选择"在此处打开命令窗口" 2.打开cmd命令窗口之后,在窗口中输入 ...

  6. 20155207 实验5 MSF基础应用

    20155207 实验5 MSF基础应用 基础问题回答 用自己的话解释什么是exploit,payload,encode exploit:让攻击方式能够发挥作用的通道,更像是没有子弹的枪,提供了攻击方 ...

  7. CodeForces-1155D Beautiful Array

    Description You are given an array \(a\) consisting of \(n\) integers. Beauty of array is the maximu ...

  8. 取两张mysql表中分别两个字段相同的值

    看起来有点绕口吧,举个例子吧,如图 两张表,字段名也不同字段gs 和另一张表 gsmc  的有些值是相同的 我们要做的就是把这个相同的值找出来 会写这个sql语句就可以 只写重点 $sql2 = &q ...

  9. Python中 list, numpy.array, torch.Tensor 格式相互转化

    1.1 list 转 numpy ndarray = np.array(list) 1.2 numpy 转 list list = ndarray.tolist() 2.1 list 转 torch. ...

  10. LintCode——合并排序数组II

    描述:合并两个排序的整数数组A和B变成一个新的数组 样例:给出A=[1,2,3,4],B=[2,4,5,6],返回 [1,2,2,3,4,4,5,6] 1.Python:先将数组B加到数组A之后,然后 ...