前面的话

  在上一篇中,概要地介绍了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%81%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:     //fieldsetcase "file":        //file inputcase "submit":      //submit buttoncase "reset":       //reset buttoncase "button":      //custom buttonbreak;                case "radio":       //radio buttoncase "checkbox":    //checkboxif (!field.checked){break;}/* falls through */default://don't include form fields without namesif (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']) ."信息保存成功!";
}
?>

转载于:https://www.cnblogs.com/yujihaia/p/7464537.html

深入理解ajax系列第二篇相关推荐

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

    前面的话 1999年,微软公司发布IE5,第一次引入新功能:允许javascript脚本向服务器发起HTTP请求.这个功能当时并没有引起注意,直到2004年Gmail发布和2005年Google Ma ...

  2. 深入理解闭包系列第二篇——从执行环境角度看闭包

    前面的话 本文从执行环境的角度来分析闭包,先用一张图开宗明义,然后根据图示内容对代码进行逐行说明,试图对闭包进行更直观的解释 图示 说明 下面按照代码执行流的顺序对该图示进行详细说明 function ...

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

    前面的话 与setTimeout和setInterval不同,requestAnimationFrame不需要设置时间间隔.这有什么好处呢?为什么requestAnimationFrame被称为神器呢 ...

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

    前面的话 javascript函数的参数与大多数其他语言的函数的参数有所不同.函数不介意传递进来多少个参数,也不在乎传进来的参数是什么数据类型,甚至可以不传参数.本文是深入理解javascript函数 ...

  5. 前端工程师技能之photoshop巧用系列第二篇——测量篇

    前端工程师使用photoshop进行的大量工作实际上是测量.本文是photoshop巧用系列第二篇--测量篇 测量信息 在网页制作中需要使用photoshop测量的信息分为两类,分别是尺寸信息和颜色信 ...

  6. 焱老师带你学习MYSQL系列 第二篇 (MYSQL 数据结构)

    相关系列链接 焱老师带你学习MYSQL系列 第六篇 (MYSQL是如何实现锁的) 焱老师带你学习MYSQL系列 第五篇 (MYSQL事务隔离级别是如何实现的) 焱老师带你学习MYSQL系列 第四篇 ( ...

  7. 阿里出品移动研发“神器” 阿里移动云系列第二篇|“移”步到位:一站式移动应用研发体系...

    摘要:2017杭州云栖大会阿里移动云峰会专场上,阿里巴巴高级技术专家小木带来一站式应用研发体系方面的演讲.本文主要以互联网的应用背景开始谈起,进而阐述了已拥有APP的企业在APP的生命周期中会遇见哪些 ...

  8. [游戏开发]Python打表工具系列 [第二篇] [打表流程描简述]

    [上一篇链接] [游戏开发]Python打表工具系列 [第一篇][IDE开发环境部署] VSCode Python环境调试_Little丶Seven的博客-CSDN博客 [前言] 第二篇文章是对流程的 ...

  9. 深入理解脚本化CSS系列第二篇——查询计算样式

    前面的话 元素的渲染结果是多个CSS样式博弈后的最终结果,这也是CSS中的C(cascade)层叠的含义.访问第一篇中的style属性只能获取行间样式,这通常来说,并不是我们想要的结果.本文将详细介绍 ...

  10. 深入理解ajax系列第三篇——响应解码

    前面的话 我们接收到的响应主体类型可以是多种形式的,包括字符串String.ArrayBuffer对象.二进制Blob对象.JSON对象.javascirpt文件及表示XML文档的Document对象 ...

最新文章

  1. 重磅!这所985高校迎来新任院士校长!他能否带领学校走出“低谷”?
  2. STM32-内存管理
  3. 设置ALV单元格可编辑状态
  4. 通过Fiddler进行手机抓包
  5. css中设置微软雅黑时,在ie6css中有些样式会失效的解决办法
  6. 对于引用的控件被拒绝访问的解决办法的补充(续)
  7. 如何选择普通索引和唯一索引?|CSDN博文精选
  8. 进程的切换和系统的一般执行过程
  9. OpenCV-Python实战(番外篇)——利用 SVM 算法识别手写数字
  10. 3.5 tensorflow2实现样本分布K-S检验 ——python实战
  11. 设计者模式之GOF23命令模式
  12. (十)stm32 GPIO口复用,重映射 RCC_APB2Periph_AFIO
  13. python 跳过_python怎么跳过异常继续执行
  14. outlook中网址连接打不开解决办法
  15. Win10微软帐户切换不回Administrator本地帐户的解决方法
  16. 易岸公考:最全版本!公务员报考条件
  17. “chmod 777-R 文件名”什么意思?
  18. HTMLCSS 【三】-- TABLES, DIVS, AND SPANS
  19. sprintf用法(很强大啊)
  20. c++之头文件基本输出,输入,名字空间,引用,内联函数,函数重载,缺省参数

热门文章

  1. UNet、U2Net 和U2NetP
  2. 帕金森日常要注意什么
  3. 我为什么活着 /罗素
  4. ZOJ4115 Wandering Robot
  5. 餐饮行业可定制APP的猜想
  6. python好玩游戏的物品清单_在你的Python平台类游戏中放一些奖励
  7. python画图x轴时间间隔_python画图把时间作为横坐标的方法
  8. php网站ssl证书,SSL证书配置 https或者切换网站的php版本
  9. 安装win11和ubuntu双系统时,因为win11登入了学校邮箱注册的微软账号,发现重启无法进入win11,需要BitLocker恢复
  10. c语言中程序的模块化是利用函数实现的吗,c语言程序设计第07章用函数实现模块化程序设计.ppt...