ajax从入门到深入精通
前言
ajax全称Asynchronous Javascript and XML。其中Asynchronous代表异步。同步于异步是描述通信模式的概念,同步机制:发送方发生请求后,需要等待接收到接收方的响应后,才能处理其他的业务。异步机制:发送方发生一个请求后,可以接着处理其他业务,不需要等待。同步机制主要是为了保证数据的一致性,异步主要是为了提高效率。 |
ajax包含的技术与原理
使用CSS和XHTML来表示。
使用DOM模型来交互和动态显示。
使用XMLHttpRequest来和服务器进行异步通信。
使用javascript来绑定和调用。
在上面几种技术中,除了XmlHttpRequest对象以外,其它所有的技术都是基于web标准并且已经得到了广泛使用的,可见ajax核心技术应该是XMLHttpRequest对象了。Ajax的原理,简单来说通过XmlHttpRequest对象来向服务器发异步请求,从服务器获得数据,然后用javascript来操作DOM而更新页面。所以我们主要弄清楚以下问题,也是本文主要解决的问题
怎样创建xmlHttpRequest对象?
怎样通过get、post传递传递数据?
怎样控制http头信息?
通过ajax能传递什么格式的数据?
怎样接收服务器传递的数据?
怎样控制数据接收的进度?
如果控制数据传递过程中的错误?
关于跨越传输的问题?
ajax简单实现
为了便于理解,我从执行过程的角度绘制了下图来解析ajax处理流程
创建xmlHttpRequest对象
因为各大浏览器厂商为了利益之争,导致了我们开发者创建xmlHttpRequest对象面临兼容性问题。
function CreateXmlHttp() {
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}else{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
}
var xmlhttp=null;
CreateXmlHttp();//创建xmlHttpRequest对象
console.log(xmlhttp);//在控制台输出xmlhttp对象
通过输出xmlhttp,我们可以查看到XMLHttpRequest对象以及其原型中包含的方法。
ajax请求实例
index.php代码如下
<meta charset="utf-8">
<script type="text/javascript">
function CreateXmlHttp() {
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}else{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
}
var xmlhttp=null;
CreateXmlHttp();//创建xmlHttpRequest对象
xmlhttp.onreadystatechange=function(){//设置状态发生变化时候监听函数
switch(xmlhttp.readyState){
case 1://调用了open的方法
console.log('调用了open的方法,xmlhttp.readyState=1');
break; case 2://调用了send方法
console.log('调用了send方法,,xmlhttp.readyState=2');
break; case 3://正在接受数据
console.log('正在接受数据,xmlhttp.readyState=3');
break; case 4://数据接收完成
if(200 == xmlhttp.status){
console.log("xmlhttp.readyState=4,请求的数据为:"+xmlhttp.responseText);
}else{ }
break;
}
console.log(xmlhttp);
}
xmlhttp.open("get", "http://127.0.0.1/a2.php", true);//调用open的方法初始化
xmlhttp.send();//调用send方法发送数据
</script>
a2.php文件如下:
<?php
for ($i=0; $i<5 ; $i++) {
var_dump('expression'.$i);
}
执行结果如下:
在论同步异步比较
在上面实例中,调用open方法采用的是异步方式去调用,现在我们将其改成同步方式调用,比较两者差异
为了便于比较将上面实例代码改为:
xmlhttp.open("get", "http://127.0.0.1/a2.php", true);//调用open的方法初始化
console.log("************"+xmlhttp.readyState+"************");
xmlhttp.send();//调用send方法发送数据
console.log("************"+xmlhttp.readyState+"************");
调用结果
现在测试同步调用,只主要讲open方法改为如下
xmlhttp.open("get", "http://127.0.0.1/a2.php", false);//调用open的方法初始化
调用结果
总结:同步与异步调用差别还是挺大的。为什么会有这样的差异呢?在同步调用中,因为浏览器调用了xmlhttp调用了send方法后,就陷入了等待服务器数据返回状态,不能进行其他的操作,等服务器返回后,直接将xmlhttp的readyState属性改了4,也就是说同步调用中,xmlhttp的readyState值直接从1跳到了4。对于异步调用,调用了send方法后,不需要等待,直接就执行了下面的代码,不需要等待。当服务器返回数据时候,就回调onreadystatechange对应的方法。
ajax进度控制
进度事件简述
在不懂ajax进度控制的时候,当看到网页中,别人实现的加载进度条,总是感觉好高达上,其实现其实并不是很难。首先我们需要了解其涉及到了6个进度事件。
- loadstart:在接收到相应的数据的第一个字节时候触发。
- progress:在接受相应期间持续不断触发,这个事件大概每50毫秒执行一次。
- error:在请求发送错误时触发
- abort:在因为调用abort()方法而终止连接时候触发
- load:在接收到完整的相应数据时触发
- loadend:在通信完成或者是触发error、abort或load事情后出发
- timeout:如果指定了timeout值,在指定时间段内未完成请求时触发。
现在我们从事件触发的角度去看,ajax通信,首先触发Loadstart事情,接下来是一个或多个progress事情,然后触发error、abort或load事情中的一个,最后以触发loadend事情结束。
为了测试以上事件,我们先做一个测试,代码如下
<meta charset="utf-8">
<script type="text/javascript">
Object.prototype.addListener=function(ev,fn){
if (this.attachEvent) {
this.attachEvent('on' + ev, fn);
}else{
this.addEventListener(ev,fn,false);
}
}
function CreateXmlHttp() {
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}else{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
}
var xmlhttp=null;
CreateXmlHttp();//创建xmlHttpRequest对象
//绑定事件,是我addListener自定义兼容各浏览器的绑定事件方法
xmlhttp.addListener('loadstart',function(){checkInfo('loadstart')});
xmlhttp.addListener('progress',function(){checkInfo('progress')});
xmlhttp.addListener('error',function(){checkInfo('error')});
xmlhttp.addListener('abort',function(){checkInfo('abort')});
xmlhttp.addListener('load',function(){checkInfo('load')});
xmlhttp.addListener('loadend',function(){checkInfo('loadend')});
xmlhttp.open("get", "http://127.0.0.1/a2.php", true);//调用open的方法初始化
xmlhttp.send();//调用send方法发送数据
function checkInfo(fnName){
console.log(fnName+'事件被触发,xmlhttp.readyState='+xmlhttp.readyState);
}
</script>
执行结果如下
通过执行结果,正好证实了,我们上面的事件触发的论述。
ajax进度条实例
现在要开始写ajax进度条了,好久没有写过进度条,还是有点小激动。
代码如下:
<meta charset="utf-8">
<script type="text/javascript">
Object.prototype.addListener=function(ev,fn){
if (this.attachEvent) {
this.attachEvent('on' + ev, fn);
}else{
this.addEventListener(ev,fn,false);
}
}
function CreateXmlHttp() {
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}else{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
}
var xmlhttp=null;
window.onload=function(){
var loadbutton=document.getElementById('loadbutton');
loadbutton.addListener('click',function(){
CreateXmlHttp();//创建xmlHttpRequest对象
//绑定事件,是我addListener自定义兼容各浏览器的绑定事件方法
xmlhttp.addListener('loadstart',loadstart);
xmlhttp.addListener('progress',progress);
xmlhttp.addListener('load',load);
xmlhttp.addListener('loadend',function(){console.log('执行结束了');});
xmlhttp.open("get", "http://127.0.0.1/ceshi.pdf", true);//调用open的方法初始化(为了便于查看效果,我让其加载一个比较大的文件,因为最开始,我尝试使用一个php文件但是看不到效果,因为它立刻出现结果)
xmlhttp.send();//调用send方法发送数据
});
}
//处理开始接受数据的画面
function loadstart(){
//当开始加载的时候,将defaultCont隐藏,将progressBox显示出来
document.getElementById('defaultCont').style.display="none";
document.getElementById('progressBox').style.display="block";
}
//处理进度
function progress(event){
//修改progressTest里面的文本提示信息以及progress的长度
var progressTest=document.getElementById('progressTest');
var progress=document.getElementById('progress');
if (event.lengthComputable) {//判断响应文本是否可以计算长度
var recivedSize= event.position;//已经接收的字节数
var totalSize=event.totalSize;//根据Content-Length相应头部确定的预期字节数
progressTest.innerText=(recivedSize/totalSize*100 )+"%";
progress.style.width=600*(recivedSize/totalSize)+"px";// 为什么是600,因为包含它的容器长度为600
}
}
//处理加载完成
function load(event){
//当开始加载的时候,将defaultCont显示出来,并将服务器返回的结果放在其里面,并将progressBox隐藏掉
document.getElementById('progressBox').style.display="none";
var defaultCont=document.getElementById('defaultCont')
defaultCont.style.display="block";
//因为加载的是一个pdf文件,所以不需要将其显示在页面上,我直接输出了xmlhttp对象
console.log(event.target);
//defaultCont.innerText=event.target.responseText;//备注,其中event.target为xmlhttp对象
//使用innerText代替innerHTML更加安全,因为如果使用innerHTML,responseText中包含html代码或JavaScript代码时候,浏览器不会解析,如果你需要其解析,当然得用innerHTML。
}
</script>
<div style="width:600px; height:auto;margin:0 auto">
<input type="button" id="loadbutton" value="加载">
<div id="defaultCont">
<img src="1.jpg" width="600px">
</div>
<div id="progressBox" style="display:none;position:relative">
<div>已经加载了:<span id="progressTest">0</span></div>
<div id="progress" style="position:absolute; width:0px; top:35px; left:0;z-index:10; height:35px; background-color:#F00"></div>
<div style="position:absolute; width:600px; top:35px; left:0; z-index:1;height:35px; background-color:#040"></div>
</div>
</div>
执行效果截图如下
ajax跨域控制
我们如果把xmlhttp的open方法改为如下:
xmlhttp.open("get", "http://localhost/a2.php", true);
在我们执行页面的时候,如果我们在服务端不进行相应的设置,就会出现如下效果:
这提示我们服务器端禁止我们跨域(跨源)请求。我们可以通过再服务端对Access-control-Allow-origin进行配置,来限定哪些域名可以访问。如果设置Access-control-Allow-origin:*代表所有的
<?php
header("Access-control-Allow-origin:*");//允许的域名 for ($i=0; $i<5 ; $i++) {
var_dump('expression'.$i);
}
然后执行代码就okey了
补充
到这里,关于ajax涉及到的主要内容基本上说完了,现在说点没有提到的。
设置头信息
通过setRequestHeader设置头信息,通过getAllResponseHeaders获取所有头信息,通过getResponseHeader获取指定的头信息。
比如:
xmlhttp.setRequestHeader("Accept-Language","zh-cn,zh;q=0.5");
ajax能传递什么格式的数据
ajax从本质上面来说就是一个请求,所以所有的类型都是支持的,平常看到说比如jquery要指定一个dataType,其实是jquery库对请求回来的response进行了预解析,序列化成对应的数据类型给,比如有服务端有个json,然后的dataType指明为text,其实返回给的还是那些内容,只是没有给序列化而已。
ajax中表单对象FormData使用
formData对象是html中form表单的抽象。其中有一个重要的方式是append,用于向formData表单对象中插入数据。
直接看如下代码(很多代码如上面雷同,就不再粘贴)
window.onload=function(){
var loadbutton=document.getElementById('loadbutton');
loadbutton.addListener('click',function(){
CreateXmlHttp();//创建xmlHttpRequest对象
//绑定事件,是我addListener自定义兼容各浏览器的绑定事件方法
xmlhttp.addListener('loadstart',loadstart);
xmlhttp.addListener('progress',progress);
xmlhttp.addListener('load',load);
xmlhttp.addListener('loadend',function(){console.log('执行结束了');});
var data=new FormData();
data.append('name','dequan');
xmlhttp.open("post", "http://127.0.0.1/a2.php", true);//调用open的方法初始化(为了便于查看效果,我让其加载一个比较大的文件,否则看不到效果)
xmlhttp.setRequestHeader("Accept-Language","zh-cn,zh;q=0.5");
xmlhttp.send(data);//调用send方法发送数据
});
}
a2.php代码如下
<?php
var_dump($_POST);
结果截图如下:
原文链接:https://blog.csdn.net/hsd2012/article/details/51152810
ajax从入门到深入精通的更多相关文章
- ajax快速入门
一.ajax简单入门 1.Ajax的实现步骤 // 1.创建ajax对象var xhr = new XMLHttpRequest();// 2.高数ajax请求地址及请求方式//第一个参数就是请求方式 ...
- ajax基础入门
补充一下Ajax的使用方法 //可以复制下面两种方法在百度上实验 //jquery的使用方法 $.ajax({ url:"index.php", success:function( ...
- PHP博大精深,入门容易,精通难,怎么才能真正学好PHP
基础最重要 (1)熟悉HTML/CSS/JS等网页基本元素,完成阶段可自行制作完整的网页,对元素属性达到熟悉程度 (2)理解动态语言的概念,运做机制,熟悉PHP语法 (3)学习如何将PHP与HT ...
- day 50 AJAX 初入门
前情提要: jq 学不好,ajax 难用好, 食用先请先确保最起码的jq 能会用 https://www.cnblogs.com/baili-luoyun/p/10473518.html jq ...
- SQL Server2008从入门到全面精通 SQL数据库视频教程
第1章 SQL Server 2008入门知识:1.SQL SERVER 2008简介2.数据库概念3.关系数据库4.范式5.E-R模型6.SQL Server 2008体系结构7.安装IIS服务8. ...
- AJAX实例入门
一.开门见山 这些时间,瞎子也看得见,AJAX正大踏步的朝我们走来.不管我们是拥护也好,反对也罢,还是视而不见,AJAX像一阵潮流,席转了我们所有的人. 关于AJAX的定义也好,大话也好,早有人在网上 ...
- AJAX从入门到放弃(二)
XHR 响应 由 driventokill 创建,路飞 最后一次修改 2015-09-25 AJAX - 服务器 响应 由于 HTTP 响应是由服务端发出的,并且服务器做出响应需要时间(比如网速慢等原 ...
- AJAX从入门到放弃(一)
AJAX可以用于创建快速动态的网页(无需重新加载整个网页的情况下,能够更新部分网页的技术) 即异步的Javascript和XML,通过后台与服务器进行少量数据交换,AJAX可以使网页实现异步更新. A ...
- Graphviz从入门到不精通
1.安装Graphviz (windows 版本,后面说linux下的安装) 1.1)下载安装文件 从graphviz官网下载 http://www.graphviz.org/Download.php ...
随机推荐
- centos7安装redis3.2.12
1.准备安装包,放在/usr/local/src/ 2.解压安装包,解压到/usr/local/ tar zxf redis-3.2.12.tar.gz -C /usr/local/ 3.cd /us ...
- Hello,Cardboard!!-如何开发一个最简单的Cardboard虚拟现实应用(一)
[原创文章,转载请注明出处,谢谢 !] 温馨提醒,本篇第一节主要介绍cardboard虚拟现实系统的组成,如果只想看如何开发的具体步骤请直接跳到第二节^_^ 前述:恕我啰嗦一下,主要照顾对cardbo ...
- mq4参考
更新: 2017/05/24 其实也就是照搬文档,主要是用到一个记一个.方便掌握 ----------------------------------------------------------- ...
- POJ3264【线段树】
求区间最值-(基础,继续) code---.. #include<cstdio> #include<iostream> #include<string.h> #in ...
- android 在一个应用中启动另一个应用
在程序开发过程当中,常遇到需要启动另一个应用程序的情况,比如在点击软件的一个按钮可以打开地图软件. 如果既有包名又有主类的名字,那就好 办了, 直接像下面就行: [html] Intent inte ...
- Jmeter逻辑控制器操作,附栗子
jmeter中的逻辑控制器确定采样器的执行顺序.右键线程组-->添加-->逻辑控制器. 一.简单控制器 简单控制器对JMeter如何处理添加到其中的采样器没有影响.只是方便我们做分组命名. ...
- NOIp2005 过河【dp+离散化】By cellur925
题目传送门 $30pts$ 状态和转移都比较好想:设$f[i]$表示跳到$i$位置,踩到的最小石子数.转移方程也很明了,为$f[i]$=$min${$f[i-j]$),,这个位置有石子时答案再加1,$ ...
- VMware安装Centos 7,网络连接问题以及解决方案
转自: https://www.cnblogs.com/owaowa/p/6123902.html 在这里表示万分感谢 在使用CentOS虚拟机后,出现了无法上网的情况,使用主机ping虚机地址可以p ...
- 529 Minesweeper 扫雷游戏
详见:https://leetcode.com/problems/minesweeper/description/ C++: class Solution { public: vector<ve ...
- Suricata的配置
见官网 https://suricata.readthedocs.io/en/latest/configuration/index.html# Docs » 8. Configuration Edit ...