红宝书是入门必备,但是里面的有些api已经被废弃,如果运行的话会报错,我查了文档才知道有些是被废弃的, 开始只是看,动手敲才能踩坑,这篇博文弄了一天,期间碰到各种问题
如果要练习ajax的,最好下一个wamp,可以在本地搭建一个服务器,非常好操作,
下面这个创建XMLHTTPRequest对象的createXHR()函数兼容了IE7以下的版本,如果不需要兼容的话只需要
new XMLHttpRequest()
function createXHR() {
alert();
if(typeof arguments.callee.activeXString != "string") {
var versions = [
"MSXML2.XMLHttp.6.0",
"MSXML2.XMLHttp.3.0",
"MSXML2.XMLHttp"
],
i,
len;
for(i=0,len = versions.length;itry{
new ActiveXObject(versions[i]);
arguments.callee.activeXString = versions[i];
break;
}catch(ex) {
}
}
}
return new ActiveXObject(arguments.callee.activeXString)
}
创建好了,我们怎么使用呢,下面来说一下
首先要调用的是open方法
xhr.open("get", "data.json", false);
看上面的代码很容易知道open有三个参数,
1. 要发送的请求类型,get、post等
2. 请求的URL,即你要请求的文件的地址相对于当前页面,绝对路径也可以
3. 是个布尔值,表示是否异步请求
需要注意的是调用open方法并不会真正发送请求,只是启动一个请求以备发送,
只能向同一个域中使用相同端口和协议的URL发送请求,若URL与启动请求的页面有任何差别,都会引发安全措施
send方法接受一个参数,作为请求主题发送的数据,如果不需要,最好传入null,因为这个参数对有的浏览器来说是必需的,调用send后,请求就会被分派到服务器
建议通过status来决定下一步操作,因为statusText在跨浏览器使用的时候不可靠,如果响应主体非XML,则responseXML属性值为null
下面是一个简单的同步请求
var xhr = createXHR();
xhr.open("get", "data.json", false);
xhr.send(null);
if((xhr.status >= 200 && xhr.status<300) || xhr.status == 304){
alert(xhr.statusText);
alert(xhr.responseText);
} else {
alert("fail" + xhr.status);
}
检测readyState属性的值,查看响应过程当前活动阶段,属性可取值:
只要readyState属性值改变就会调用readystatechange事件,不过必须在调用open之前指定,确保跨浏览器的兼容
xhr.onreadystatechange = function() {
console.log(this);
if(xhr.readyState == 4){
if((xhr.status >= 200 && xhr.status<300) || xhr.status == 304){
console.log(xhr.statusText);
console.log(xhr.responseText);
} else {
console.log("fail" + xhr.status);
}
}
console.log("改变");
}
xhr.open("get", "data.json", true);
xhr.send(null);
运行结果截图
上面的代码中,不要使用this,用实例对象xhr,因为回调的时候,作用域就会改变
如果使用this对象,在有的浏览器中会导致函数执行失败,或者导致异常.因此使用实际的xhr对象实例变量比较靠谱.这里也没搜到具体的解释,只是说调用这个可能会因为作用于问题而失败
这里的头部信息有两种,
下面头信息一般会随XHR请求发送
xhr.onreadystatechange = function() {
if(xhr.readyState == 4){
if((xhr.status >= 200 && xhr.status<300) || xhr.status == 304){
console.log(xhr.statusText);
alert(xhr.responseText);
} else {
alert("fail" + xhr.status);
}
}
}
xhr.open("get", "data.json", true);
xhr.setRequestHeader("myheader", "myvalue");
xhr.send(null);
建议:字段名称自己想名字,不要使用浏览器定义的,有的浏览器允许我们重写默认的头部信息有的不允许,所以这样有可能影响服务器响应。
xhr.onreadystatechange = function() {
if(xhr.readyState == 4){
if((xhr.status >= 200 && xhr.status<300) || xhr.status == 304){
console.log(xhr.statusText);
console.log(xhr.responseText);
console.log(xhr.getAllResponseHeaders());
} else {
alert("fail" + xhr.status);
}
}
}
xhr.open("get", "data.json", false);
xhr.setRequestHeader("myheader", "myvalue");
xhr.send(null);
常用于向服务器查询某些请求,可以将查询字符串追加到URL末尾,对xhr来说,追加的字符串的每个参数必须经过编码,所有名值对用&隔开
xhr.open("open", "example.php?name1=value1&name2=value2", true);
创建一个函数向传入的URL末尾追加经过编码的字符串
function addURLParam(url,name,value) {
if(url.indexof("?") == -1){
url += '?';
} else{
url+= '&';
}
url+=encodeURIComponent(name) + '=' + encodeURIComponent(value);
return url;
}
小例子:
document.addEventListener('click',function() {
var xhr = new createXHR();
var url = 'demo.php?rand='+Math.random();
url=addURLParam(url,'name','Le&e');
url=addURLParam(url,'age',100);
alert('url: ' + url);
xhr.onreadystatechange = function() {
if(xhr.readyState == 4){
try{
if((xhr.status >= 200 && xhr.status<300) || xhr.status == 304){
console.log(xhr.statusText);
alert('responseText: ' + xhr.responseText);
console.log(xhr.getAllResponseHeaders());
} else {
alert("fail" + xhr.status);
}
} catch(e) {
}
}
};
xhr.open("get", url,true);
xhr.send(null);
});
function addURLParam(url,name,value) {
if(url.indexOf("?") == -1){
url += '?';
} else{
url+= '&';
}
url+=encodeURIComponent(name) + '=' + encodeURIComponent(value);
return url;
}
我的php文件,中文会有乱码问题,所以要设置utf-8
header('Content-Type:text/html;charset=utf-8');
// echo Date('Y-M-D H:i:s');
print_r($_GET);
// print_r($_POST);
if($_GET['name']=='Le&e'){
echo '噜瑞';
}
?>
用于向服务器发送应该被保存的数据,把数据作为请求的主体提交,它请求的主体可以包含非常多的数据,且格式不限。。
document.addEventListener('click',function() {
var xhr = new createXHR();
var url = 'demo.php?rand='+Math.random();
alert('url: ' + url);
xhr.onreadystatechange = function() {
if(xhr.readyState == 4){
try{
if((xhr.status >= 200 && xhr.status<300) || xhr.status == 304){
console.log(xhr.statusText);
alert('responseText: ' + xhr.responseText);
console.log(xhr.getAllResponseHeaders());
} else {
alert("fail" + xhr.status);
}
} catch(e) {
}
}
};
xhr.open("post", url,true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); // 模拟表单提交
xhr.send('name=Lee&age=100');
});
function addURLParam(url,name,value) {
if(url.indexOf("?") == -1){
url += '?';
} else{
url+= '&';
}
url+=encodeURIComponent(name) + '=' + encodeURIComponent(value);
return url;
}
php文件
header('Content-Type:text/html;charset=utf-8');
print_r($_GET);
print_r($_POST);
if($_POST['name']=='Lee'){
echo '噜瑞阿';
}
?>
为表单数据的序列化,以及创建与表单格式相同的数据提供便利。
var data= new FormData();
data.append("name", "lurui");
append方法接受两个参数,键、值,分别对应表单字段的名字和字段中包含的值,可以添加任意多个键值对,通过向FormData构造函数中传入表单元素,也可以用表单元素的数据预先向其中填入键值对:
var data= new FormData(document.forms[0]);
data.append()
var xhr = createXHR();
xhr.onreadystatechange = function() {
if(xhr.readyState == 4){
if((xhr.status >= 200 && xhr.status<300) || xhr.status == 304){
console.log(xhr.responseText);
} else {
alert("fail" + xhr.status);
}
}
};
xhr.open("post", "data.json", true);
var form = document.getElementById("user-form");
xhr.send(new FormData(form));
IE8、timeout属性,表示请求在多长时间后没接收到响应就执行ontimeout事件
用于替代onreadystatechange(),响应接收完毕触发load,因为没必要检查readystate属性,load接收一个event对象,其target属性指向XHR对象实例,按理来说通过target就可以访问XHR对象的所有属性和方法了,然而并非所有浏览器都实现event对象,所以不能用,只要浏览器接受到服务器响应不管状态如何都会触发load,而这意味着你还是要检测status属性,才可以确定数据是否可用。
open方法之前指定。
xhr.onprogress = function(event) {
console.log(event.position);
var divs = document.getElementById("a");
if(event.lengthComputable){
divs.innerHTML = "received " + event.position + ' of ' + event.totalSize + ' bytes';
}
}
FF、chrome显示undefined,上面的截图是360的运行结果,其实他们都不支持totalSise,要换成total,position要换成loaded,但是如果不换IE也会有结果不报错,但是FF、chrome会报undefined,不显示正确结果
通过XHR实现ajax通信的一个主要限制是跨域安全策略,默认情况下,XHR对象只能访问与包含他的页面位于同一个域中的资源,可以防止恶意行为。
CORS跨资源共享
先看这个图,检查了好几遍代码无误后我去百度,得到的结果
IE8引用了XDR(XDomainRequest)类型,此对象与XHR类似,但可以实现安全可靠的跨域通信,
XHR与XDR的不同之处
看一下浏览器对xhr的支持
PC端:
移动端:
XHR跨域请求时,url写成绝对地址即可,通过跨域XHR对象也可以访问status,statusText属性,也支持同步请求,跨域XHR有一些必须的限制:
1. 不能使用setRequestHeader自定义头部
2. 不能发送和接收cookie
3. 调用getAllResponseHeaders方法总会返回空字符串
由于无论是同源还是跨源都是用相同的接口,因此对于本地资源最好用相对url,对于跨源用绝对url,这样可以消除歧义,避免出现限制访问头部或本地cookie信息问题。
透明服务器验证机制,支持使用我们的自定义头部、get或post以外的方法、以及不同类型的主体内容
function createCORSRequest(method,url) {
var xhr = new XMLHttpRequest();
if("withCredentials" in xhr){
xhr.open(method,url,true);
} else if(typeof XDomainRequest != 'undefined') {
xhr = new XDomainRequest();
xhr.open(method,url);
} else{
xhr =null;
}
return xhr;
}
function handleResponse(response) {
console.log(response);
alert("ip address" + response.ip + " in " + response.city + "," + response.region_name);
}
var script = document.createElement("script");
script.src = "http://freegeoip.net/json/?callback=handleResponse";
document.body.insertBefore(script, document.body.firstChild);
更高级的ajax技术。ajax是一种页面向服务器请求数据的技术,Comet则是服务器向页面推送数据的技术,让信息近乎实时的推送到页面上,适合体育比赛分数、股票报价等。
短轮询:即浏览器定时向服务器发送请求,检测有没有更新的数据
实现Comet的方法
实现HTTP流原理:通过侦听readystatechange(如果支持)事件及检测readyState值是否为3,利用xhr对象实现。随着不断从服务器接收数据,readyState值会周期性的变为3,当为3时,responseText中就会保存所有接受到的数据,此时较之前接受到的数据决定从什么位置开始去的最新的数据,
实现代码如下:
function createStreamingClient(url,progress,finished) {
var xhr = new createXHR(),
received = 0;
xhr.open("get",url,true);
xhr.onreadystatechange =function() {
var result;
if(xhr.readyState == 3) {
result = xhr.responseText.substring(received);
received += result.length;
progress(result);
} else if(xhr.readyState ==4) {
finished(xhr.responseText);
}
};
xhr.send(null);
return xhr;
}
// 实例
var client = createStreamingClient("data.json", function(data) {
console.log("received : " + data)
}, function(data) {
alert("done");
})
贴一段书上的原话
MDN上的websockets的浏览器支持情况
实例化
var socket = new WebSocket("ws://www.example.com/server.php");
//关闭时用
socket.close();
注意: 构造函数必须传入绝对URL,同源策略对websockets不适用,因此它可以打开任何站点的连接,是否能与某个域中页面通信完全取决与服务器
表示当前状态的readyState(类比XHR,不过两者的属性值不同),他永远从0开始。调用close后,值变为2(正在关闭),关闭后变为3. 属性值:
websockets没有readystatechange事件
websockets只能通过连接发送纯文本数据,所以对于复杂的数据,在发送前要进行序列化(JSON.Stringify())
当服务端向客户端发来消息时,触发onmessage(),他把返回的数据(字符串)保存在event.data属性中。
websockets其他事件:
socket.onopen = function(){};
socket.onerror = function(){};
socket.onclose = function(event){
console.log(event.wasClean + event.code + event.reason);
}
如上,是定义方法,而且可以看出只有onclose接收一个对象,对象有三个属性,分别表示: